Co robi `. []. Foo []` w bash? Dlaczego pasuje do „..”?

16

Spójrz na następujące:

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

Najwyraźniej wydaje się, że jest to coś globalnego, ale nie rozumiem, w jaki sposób wynik się łączy. Z mojego zrozumienia []jest pusta klasa postaci. Byłoby intuicyjnie, gdyby

  • pasował tylko do pustego łańcucha; w tym przypadku spodziewałbym się, że bash powiela się w całości, ponieważ nic nie pasuje do tego w tym katalogu, ale pasuje również do rzeczy ..aliases(w pierwszym przykładzie),
  • albo w ogóle nic; w tym przypadku spodziewałbym się, że bash również odtworzy ciąg znaków.

To jest z wydaniem GNU bash, wersja 4.4.23 (1).

Jonas Schäfer
źródło

Odpowiedzi:

25

[Zaczyna zestawu. Zestaw jest zakończony przez ]. Istnieje jednak sposób, aby mieć go ]jako część zestawu, a mianowicie ]jako pierwszy znak. Ponieważ pusty zestaw nie ma żadnego sensu, nie jest to dwuznaczne.

Tak więc twoje przykłady to w zasadzie kropka, po której następuje zestaw zawierający kropkę, dlatego pasuje do dwóch kropek.

Późniejsze przykłady nie znajdują żadnych plików i dlatego są zwracane dosłownie.

RalfFriedl
źródło
4

Tylko ciągi cytowane nie podlegają globowaniu:

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

Ale ciągi bez cudzysłowu podlegają globowaniu. Niecytowany ciąg znaków, który zawiera *lub ?OR (prawidłowy) [](wyrażenie uchwytem) zostaną zmienione przez listę plików, które go pasują. W taki sam sposób, jak a *przekształci się we wszystkie pliki w pasującym katalogu, a a ?dopasuje pliki tylko jednego znaku, a (prawidłowe) []dopasuje pliki ze znakami w nawiasach. Kropka jest poprawnym znakiem:

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

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

Aby móc dopasować ], powinien być to pierwszy znak w nawiasach:

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

Wyrażenie pustego nawiasu nie ma sensu (i nie jest rozwinięte):

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

Dlatego to działa:

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

Dla [idei jest podobna:

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

ale może być w dowolnym miejscu wyrażenia w nawiasach:

$ 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

Napisany ciąg .[].foo[]będzie pasował do kropki, po której następuje a ], a ., a f, a olub a [. To jest podobne do:

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

I będzie pasować następująco:

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

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

Należy pamiętać, że wpisu katalogu ..nie trzeba tworzyć, ponieważ domyślnie istnieje on w każdym katalogu. Ale zwykła kropka .nie będzie pasować do globu, ponieważ musi być dopasowana jawnie (poprzez użycie kropki).

Ale to nie będzie pasować, ..aliasesponieważ wyrażenie w nawiasie pasuje tylko do jednego znaku. Aby dopasować kilka znaków, musisz użyć *(cokolwiek):

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

$ echo .[].aliases[]*
.. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l
Izaak
źródło