Что `. []. Foo []` делает в bash? Почему это соответствует `..`?

16

Посмотрите на следующее:

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

По-видимому, это что-то поглощает, но я не понимаю, как получается результат. Из моего понимания []пустой класс персонажей. Было бы интуитивно понятно, если

  • это соответствует только пустой строке; в этом случае я ожидаю, что bash будет воспроизводиться полностью, поскольку в этом каталоге ничего не совпадает, но также совпадают с такими вещами, как ..aliases(в первом примере),
  • или вообще ничего; в этом случае я ожидаю, что bash также полностью воспроизведет строку.

Это с GNU bash, версия 4.4.23 (1) -релиз.

Йонас Шефер
источник

Ответы:

25

[Начинается набор. Набор заканчивается ]. Но есть способ иметь ]как часть набора, и это указать ]первый символ. Поскольку пустой набор не имеет никакого смысла, это не является двусмысленным.

Таким образом, ваши примеры в основном представляют собой точку, за которой следует набор, содержащий точку, поэтому она соответствует двум точкам.

Более поздние примеры не находят никаких файлов и поэтому возвращаются дословно.

RalfFriedl
источник
4

Только цитируемые строки не подлежат сглаживанию:

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

Но строки без кавычек могут быть повреждены. Строка без кавычек, содержащая *или a ?или (допустимое) [](выражение в скобках), будет изменена списком файлов, которые ей соответствуют. Аналогично тому, как a *преобразуется во все файлы в соответствующем каталоге, а a ?будет сопоставлять файлы только с одним символом, так (действительный) []будет сопоставлять файлы с символами в скобках. Точка является допустимым символом:

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

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

Чтобы иметь возможность соответствовать a, ]это должен быть первый символ в скобках:

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

Пустое выражение в скобках не имеет смысла (и не раскрывается):

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

Вот почему это работает:

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

По [идее похоже:

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

но это может быть в любой позиции в выражении в скобках:

$ 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

Отправленная вами строка .[].foo[]будет соответствовать точке, за которой следуют a ], a ., a f, a oили a [. Это похоже на:

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

И это будет соответствовать следующим образом:

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

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

Обратите внимание, что запись каталога ..не нужно создавать, поскольку она существует внутри каждого каталога по умолчанию. Но простая точка .не будет сопоставлена ​​глобусом, поскольку она должна быть явно найдена (фактически используя точку).

Но это не будет совпадать, так ..aliasesкак выражение в скобках будет соответствовать только одному символу. Чтобы сопоставить несколько символов, вам нужно использовать *(что угодно):

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

$ echo .[].aliases[]*
.. .[ .] .a ..a ..ali ..alias ..aliases ..i ..l
Исаак
источник