Por que é echo {1,2,3}expandido para 1 2 3, que é um comportamento esperado, enquanto echo [[:digit:]]retorna [[:digit:]]enquanto eu esperava que ele imprimisse todos os dígitos de 0até 9?
Porque são duas coisas diferentes. Este {1,2,3}é um exemplo de expansão de chaves . A {1,2,3}construção é expandida pelo shell , antes echomesmo de vê-lo. Você pode ver o que acontece se você usar set -x:
$ set-x
$ echo {1,2,3}+ echo 123123
Como você pode ver, o comando echo {1,2,3}é expandido para:
echo 123
No entanto, [[:digit:]]é uma classe de caracteres POSIX . Quando você o entrega echo, o shell também o processa primeiro, mas desta vez está sendo processado como um shell glob . funciona da mesma maneira como se você executasse, o echo *que imprimirá todos os arquivos no diretório atual. Mas [[:digit:]]é um glob de shell que irá corresponder a qualquer dígito. Agora, no bash, se um shell glob não corresponder a nada, ele será expandido para si mesmo:
Se a glob corresponder a algo, isso será impresso:
$ echo /e*c+ echo /etc/etc
Nos dois casos, echoapenas imprime o que o shell /etcsolicitar , mas no segundo caso, como a glob corresponde a algo ( ), é solicitado que imprima essa coisa.
Portanto, como você não possui nenhum arquivo ou diretório cujo nome consiste em exatamente um dígito (que é o [[:digit:]]que corresponderia), o globo é expandido para si mesmo e você obtém:
$ echo [[:digit:]][[:digit:]]
Agora, tente criar um arquivo chamado 5e executando o mesmo comando:
$ echo [[:digit:]]5
E se houver mais de um arquivo correspondente:
$ touch 15
$ echo [[:digit:]]15
Isso está documentado na man bashexplicação das nullglobopções que desabilitam esse comportamento:
nullglobIfset, bash allows patterns which match no files (seePathnameExpansion above) to expand to a null string,
rather than themselves.
Veja também shopt -s failglobpara obter um comportamento mais útil semelhante ao das conchas modernas como zshou fish.
Stéphane Chazelas
Eu concordo com Stéphane, use failglob. nullglobpode causar problemas inesperados, por exemplo, ao colar um URL que tenha um ?.
Kevin
1
Claro, eu apenas mencionei nullglobpara demonstrar que o padrão está sendo interpretado como um globo pela casca.
terdon
14
{1,2,3}Como expansão entre chaves , ela se expande para as palavras listadas sem levar em consideração o significado delas.
[...]é um grupo de caracteres usado na expansão do nome do arquivo (ou curinga ou glob) de maneira semelhante ao asterisco *e ao ponto de interrogação ?. Corresponde a qualquer caractere único listado ou caracteres membros de grupos nomeados, como [:digit:]se eles estivessem listados. O comportamento padrão da maioria dos shells é deixar o curinga como está se não houver arquivos correspondentes.
(Observe que você não pode realmente transformar um curinga / padrão no conjunto de seqüências de caracteres que ele corresponderia. O asterisco pode corresponder a qualquer sequência de qualquer comprimento, portanto, expandir qualquer padrão que a contenha produziria uma lista infinita de seqüências de caracteres.)
Assim:
$ bash -c 'echo [[:digit:]]'# bash leaves it as-is[[:digit:]]
$ zsh -c 'echo [[:digit:]]'# zsh by default complains if no match
zsh:1: no matches found:[[:digit:]]
$ touch 13 d i g t
$ bash -c 'echo [[:digit:]]'# now there are two matches13# note that d, i, g and t do NOT match
Mas ainda:
$ bash -c 'echo {1,2,3}'123
Ambos são expandidos pelo shell , não importa se o comando que você está executando é ls, ou echoou rm. Observe também que, se qualquer um desses itens for citado, eles não serão expandidos:
$ bash -c 'echo "[[:digit:]]"'# even though matching files still exist[[:digit:]]
$ bash -c 'echo "{1,2,3}"'{1,2,3}
Obrigado pela sua resposta, sou novo no Linux então deixe-me por favor, pergunte-lhe como eco está relacionada a arquivos 1 3, a sua função é imprimir os seus argumentos para stdout não à procura de arquivos como a meu conhecimento
Abdallah Talaat
1
@AbdAllahTalaat isso não tem nada a ver com eco, na verdade. O shell (por exemplo, bash) "expandirá" o [[:digit:]]antes de passá-lo para echo, então echonunca o vê [[:digit:]], ele vê apenas 1 3. Você pode ver isso em ação executando, o set -xque imprimirá os comandos reais sendo executados (execute set +xpara desativá-lo novamente).
terdon
@AbdAllahTalaat, echonão procura por arquivos, o shell o faz, antes de executar o arquivo echo.
Ilkkachu 07/03/19
Especialmente porque acho que no DOS / Windows os utilitários expandem os curingas, não o shell. (Eu talvez
esteja
desculpe pessoal, mudei a resposta correta para a resposta do tedron porque o comentário dele continha o significado de que bash é o que o trabalho não ecoa ... a resposta dele também continha esse significado .. todos vocês me ajudaram ... eu gostaria de poder colocar resposta correta para todas as suas respostas e comentários
Abdallah Talaat
4
{1,2,3}(e, por exemplo, {1..3}são expansões entre chaves . Eles são interpretados pelo shell antes da execução do comando.
[[:digit:]]é um token de correspondência de padrão , mas você não o está usando em um local com arquivos que correspondam a esse padrão. Se você usar uma correspondência de padrão que não possui correspondências, ela se expandirá para si mesma:
Respostas:
Porque são duas coisas diferentes. Este
{1,2,3}
é um exemplo de expansão de chaves . A{1,2,3}
construção é expandida pelo shell , antesecho
mesmo de vê-lo. Você pode ver o que acontece se você usarset -x
:Como você pode ver, o comando
echo {1,2,3}
é expandido para:No entanto,
[[:digit:]]
é uma classe de caracteres POSIX . Quando você o entregaecho
, o shell também o processa primeiro, mas desta vez está sendo processado como um shell glob . funciona da mesma maneira como se você executasse, oecho *
que imprimirá todos os arquivos no diretório atual. Mas[[:digit:]]
é um glob de shell que irá corresponder a qualquer dígito. Agora, no bash, se um shell glob não corresponder a nada, ele será expandido para si mesmo:Se a glob corresponder a algo, isso será impresso:
Nos dois casos,
echo
apenas imprime o que o shell/etc
solicitar , mas no segundo caso, como a glob corresponde a algo ( ), é solicitado que imprima essa coisa.Portanto, como você não possui nenhum arquivo ou diretório cujo nome consiste em exatamente um dígito (que é o
[[:digit:]]
que corresponderia), o globo é expandido para si mesmo e você obtém:Agora, tente criar um arquivo chamado
5
e executando o mesmo comando:E se houver mais de um arquivo correspondente:
Isso está documentado na
man bash
explicação dasnullglob
opções que desabilitam esse comportamento:Se você definir esta opção:
fonte
shopt -s failglob
para obter um comportamento mais útil semelhante ao das conchas modernas comozsh
oufish
.failglob
.nullglob
pode causar problemas inesperados, por exemplo, ao colar um URL que tenha um?
.nullglob
para demonstrar que o padrão está sendo interpretado como um globo pela casca.{1,2,3}
Como expansão entre chaves , ela se expande para as palavras listadas sem levar em consideração o significado delas.[...]
é um grupo de caracteres usado na expansão do nome do arquivo (ou curinga ou glob) de maneira semelhante ao asterisco*
e ao ponto de interrogação?
. Corresponde a qualquer caractere único listado ou caracteres membros de grupos nomeados, como[:digit:]
se eles estivessem listados. O comportamento padrão da maioria dos shells é deixar o curinga como está se não houver arquivos correspondentes.(Observe que você não pode realmente transformar um curinga / padrão no conjunto de seqüências de caracteres que ele corresponderia. O asterisco pode corresponder a qualquer sequência de qualquer comprimento, portanto, expandir qualquer padrão que a contenha produziria uma lista infinita de seqüências de caracteres.)
Assim:
Mas ainda:
Ambos são expandidos pelo shell , não importa se o comando que você está executando é
ls
, ouecho
ourm
. Observe também que, se qualquer um desses itens for citado, eles não serão expandidos:fonte
[[:digit:]]
antes de passá-lo paraecho
, entãoecho
nunca o vê[[:digit:]]
, ele vê apenas1 3
. Você pode ver isso em ação executando, oset -x
que imprimirá os comandos reais sendo executados (executeset +x
para desativá-lo novamente).echo
não procura por arquivos, o shell o faz, antes de executar o arquivoecho
.{1,2,3}
(e, por exemplo,{1..3}
são expansões entre chaves . Eles são interpretados pelo shell antes da execução do comando.[[:digit:]]
é um token de correspondência de padrão , mas você não o está usando em um local com arquivos que correspondam a esse padrão. Se você usar uma correspondência de padrão que não possui correspondências, ela se expandirá para si mesma:fonte