O que '. []. foo []' faz no bash? Por que combina com '..'?

16

Veja o seguinte:

$ echo .[].aliases[]
..
$ echo .[].foo[]
..
$ echo .[].[]
..
$ echo .[].xyz[]
..
$ echo .xyz[].xyz[]
.xyz[].xyz[]
$ echo .xyz[].[]
.xyz[].[]

Aparentemente isso parece estar fazendo algo, mas eu não entendo como o resultado vem junto. Pelo que entendi, [] é uma classe de caracteres vazia. Seria intuitivo se

  • combinava apenas com a string vazia; Nesse caso, eu espero que o bash se reproduza na íntegra, já que nada corresponde a ele neste diretório, mas também corresponde a coisas como ..aliases (no primeiro exemplo),
  • ou nada; Nesse caso, eu esperaria que o bash reproduzisse a string no total também.

Isto é com o GNU bash, versão 4.4.23 (1) -release.

    
por Jonas Schäfer 11.08.2018 / 18:16

2 respostas

25

O [ inicia um conjunto. Um conjunto é finalizado por ] . Mas existe uma maneira de ter ] como parte do conjunto, e isso é para especificar o ] como o primeiro caractere. Como um conjunto vazio não faz qualquer sentido, isso não é ambíguo.

Assim, seus exemplos são basicamente todos um ponto seguido por um conjunto que contém um ponto, portanto, corresponde a dois pontos.

Os exemplos mais recentes não encontram nenhum arquivo e, portanto, são retornados textualmente.

    
por 11.08.2018 / 18:20
4

Apenas as strings entre aspas não estão sujeitas a globbing:

$ echo ".[].aliases[]"
.[].aliases[]

Mas as strings não citadas estão sujeitas a globbing. Uma sequência sem aspas que contém um * ou um ? ou (válido) [] (expressão de colchetes) será modificada pela lista de arquivos correspondentes. Da mesma forma que um * se transformará em todos os arquivos no diretório correspondente e um ? corresponderá aos arquivos de apenas um caractere, um (válido) [] corresponderá aos arquivos com os caracteres dentro dos colchetes. Um ponto é um caractere válido:

$ echo a[.]b
a[.]b

$ touch "a.b"
$ echo a[.]b
a.b

Para poder corresponder um ] , este deve ser o primeiro caractere entre parênteses:

$ touch "a]b"
$ ls a[]]b
a]b

Uma expressão de colchetes vazios não faz sentido (e não é expandida):

$ touch ab
$ ls a[]b
ls: cannot access 'a[]b': No such file or directory

É por isso que isso funciona:

$ touch a]c abc afc azc a:c a?c aoc 
$ ls a[]bfz:?]c
abc  a:c  a?c  a]c  afc  azc

Para [ , a ideia é semelhante:

$ touch a[c
$ ls a[[]c
a[c

mas poderia estar em qualquer posição em uma expressão de colchetes:

$ ls a[]bf[z:?]c
abc  a:c  a?c  a[c  a]c  afc  azc

$ ls a[]bfz:?[]c
abc  a:c  a?c  a[c  a]c  afc  azc

A string que você postou .[].foo[] corresponderá a um ponto seguido por ] , . , f , o ou [ . É semelhante a:

$ echo a[].foo[]c
a[c a]c afc aoc

E será igual ao seguinte:

$ touch .] .f .o .[ .a .b .z

$ echo .[].foo[]
.. .[ .] .f .o

Observe que a entrada de diretório .. não precisa ser criada como existe dentro de todos os diretórios por padrão. Mas um ponto simples . não será correspondido por um glob, pois ele precisa ser correspondido explicitamente (usando um ponto).

Mas isso não corresponderá a ..aliases , pois a expressão de colchetes corresponderá apenas a um caractere. Para combinar vários caracteres, você precisa usar um * (qualquer coisa):

$ touch ..a ..l ..i ..aliases ..alias ..ali
$ echo .[].aliases[]
.. .[ .] .a

$ echo .[].aliases[]*
.. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l
    
por 12.08.2018 / 00:37