Почему я не могу использовать! (Один шаблон) в zsh даже после включения kshglob?

8

Это работает в Bash:

touch a b c
echo !(a)

Если я выполняю вышеупомянутый скрипт в zsh (с kshglobon), он жалуется:

zsh: number expected

Если я добавлю |после a, это работает:

echo !(a|)

Почему?

dedowsdi
источник

Ответы:

10

Потому что в этом случае он конфликтует с пустыми глобальными квалификаторами, поскольку находится в конце шаблона. *(a1)берется как файлы, к которым последний раз обращались в последний день. (a1)рассматривается как глобус квалификатор. Так что в вашем !(a)случае zsh жалуется на пропущенное количество дней после aквалификатора glob (здесь применяется к названному файлу !).

В zshglobs (...)группирование в основном используется для (foo|bar)чередования, поэтому добавление |является документированным способом убедиться, что трейлинг (...)не рассматривается как квалификатор glob.

Другая документированная альтернатива - удвоить скобки ( !((a))), или вы можете добавить пустой спецификатор glob (например !(a)(-)).

Чтобы полностью устранить эту неоднозначность, можно отключить bare_glob_qualпараметр ( set +o bareglobqual), после которого необходимо написать квалификатор glob с extendedglob (#q...)синтаксисом ( *(#qa1)здесь).

kshglobВариант ( добавлена в 1998 году , примерно в то же время bashдобавил его extglobхотя баш не было никакого расширенного Glob до этого) в основном там для kshрежима эмуляции ( emulate ksh), для zshчтобы иметь возможность запускать kshскрипты, где kshglobвключен и bareglobqualвыключен. Когда он был впервые представлен, после включения kshglobвам нужно было указать спецификаторы глобуса, -(...)чтобы избежать такого рода конфликтов, но это вызвало слишком большую путаницу и противоречило @-(...)синтаксису ksh93, (#q...)а bareglobqualпараметры и были представлены позже.

zshпользователи обычно предпочитают собственные расширенные set -o extendedglobоператоры glob ( ) в zsh, которые легче вводить (для большинства) и более мощные (чем ksh88, с которыми kshglobтакже можно ознакомиться в bash -O extglob).

Например, !(foo)будет написано ^foo. !(foo|)barЭквивалент бы , однако, больше как (^(foo|))bar.

Другие переводы ksh88 -> zsh:

  • *(x) -> x#
  • +(x) -> x##
  • @(x|y) -> x|y
  • ?(x) -> (x|)

Некоторые переводы ksh93 -> zsh:

  • ~(i:x)-> (#i)x(без учета регистра)
  • ~(N)x-> x(N)(nullglob, возник из zsh)
  • {1,5}(x) -> x(#c1,5)
  • @(foo&bar)-> foo~^barили^(^foo|^bar)

Некоторые найдены только в zsh:

  • <1-23> (диапазон десятичных чисел)
  • pattern~except
  • pattern(glob-qualifier) (убийственная особенность Zsh Globs)
  • (pattern/)#(любой уровень подкаталогов, соответствующих pattern; **/упрощенная версия (*/)#также была добавлена ​​в ksh93 и bash недавно)
  • ***/* (рекурсивное сглаживание по символическим ссылкам).
  • (#a1)foobar (приблизительное соответствие, допускающее некоторые ошибки, здесь 1)
  • ...
Стефан Шазелас
источник