Мой вопрос возникает из-за того, как хранение регулярного выражения в переменной оболочки позволяет избежать проблем с цитированием символов, которые являются специальными для оболочки? ,
Почему есть ошибка:
$ [[ $a = a|b ]] bash: syntax error in conditional expression: unexpected token `|' bash: syntax error near `|b'
Внутри
[[ ... ]]
второго операнда,=
как ожидается, будет шаблон сглаживания.Разве это
a|b
не допустимый шаблон сглаживания? Можете ли вы указать, какое правило синтаксиса оно нарушает?Некоторый комментарий ниже указывает, что
|
интерпретируется как труба.Затем
=
измените шаблон глобуса на шаблон=~
регулярного выражения, чтобы заставить|
работать$ [[ $a =~ a|b ]]
Я узнал из Learning Bash p180 в моем предыдущем посте, который
|
распознается как труба в начале интерпретации, даже перед любыми другими шагами интерпретации (включая синтаксический анализ условных выражений в примерах). Итак, как можно|
распознать в качестве оператора регулярного выражения при использовании=~
, не будучи признанным в качестве канала в недопустимом использовании, так же, как при использовании=
? Это заставляет меня думать, что синтаксическая ошибка в части 1 не означает, что|
она интерпретируется как конвейер.Каждая строка, которую оболочка читает из стандартного ввода или скрипта, называется конвейером; он содержит одну или несколько команд, разделенных нулем или несколькими символами канала (|). Для каждого считываемого конвейера оболочка разбивает его на команды, настраивает ввод / вывод для конвейера, а затем выполняет для каждой команды следующее (рисунок 7-1):
Благодарю.
|
он особенный) включен по умолчанию в правой части[[ $var = $pattern ]]
. Было бы интересно изолировать версии иshopt
конфигурации опций, где это поведение наблюдается - если это только те, гдеextglob
включено, либо по умолчанию, либо в явной конфигурации, ну, вот и мы.pattern='a|b'
а затем расширить без$pattern
кавычек на RHS.Ответы:
Там нет веских причин, почему
Должен сообщать об ошибке вместо проверки, является ли $ a
a|b
строкой, а[[ $a =~ a|b ]]
не возвращает ошибку.Единственная причина в том, что
|
обычно (снаружи и внутри[[ ... ]]
) специальный символ. В этой[[ $a =
позицииbash
ожидается тип токена, который является обычным WORD, как аргументы или цели перенаправлений в командной строке обычной оболочки (но как если быextglob
опция была включена с bash 4.1).( СЛОВО здесь я ссылаюсь на слово в гипотетической грамматике оболочки, подобной описанному в спецификации POSIX , это то, что оболочка будет анализировать как один токен в простой командной строке оболочки, а не другое определение слов, подобных английскому один из последовательности букв или последовательности , не являющихся интервалы между символами.
foo"bar baz"
,$(echo x y)
, два таких СЛОВО с).В обычной командной строке оболочки:
По
echo a
трубопроводуb
.a|b
это не СЛОВО , это три токена :a
СЛОВО ,|
токен и токенb
СЛОВА .При использовании в
[[ $a = a|b ]]
,bash
ожидает WORD, который он получает (a
), но затем находит неожиданный|
токен, который вызывает ошибку.Интересно,
bash
не жалуется на:Поскольку теперь это
a
токен, за которым следует||
токен, за которымb
следует синтаксический анализ:Который проверяет, что
$a
этоa
или чтоb
строка не пуста.Сейчас в:
bash
не может иметь такое же правило синтаксического анализа. Наличие одного и того же правила синтаксического анализа будет означать, что вышеприведенное приведет к ошибке и что нужно будет процитировать это,|
чтобы убедиться,a|b
что это одно слово . Но, начиная с Bash 3.2, если вы делаете:Это больше не совпадает с
a|b
регулярным выражением, а сa\|b
регулярным выражением. То есть кавычки оболочки имеют побочный эффект удаления специального значения операторов регулярных выражений. Это особенность, поэтому поведение аналогично тому[[ $a = "?" ]]
, но шаблоны подстановочных знаков (используемые в[[ $a = pattern ]]
) являются СЛОВАМИ оболочки (например, используются в globs), а регулярные выражения - нет.Таким образом ,
bash
должно рассматривать все расширенные операторы регулярных выражений, которые в противном случае обычно специальные символы оболочки , такие как|
,(
,)
иначе при разборе аргумента=~
оператора.Тем не менее, обратите внимание, что в то время как
сейчас работает,
не делает. Тебе нужно:
Который в предыдущих версиях
bash
некорректно совпадал с обратной косой чертой. Это было исправлено, ноИмеет ли не соответствовать на обратной косой черты , как это следует, например. Потому что
bash
не может понять, что)
находится в скобках, поэтому избегает,)
чтобы привести к[^]\)]
регулярному выражению, которое соответствует любому символу, кроме]
,\
и)
.ksh93
есть гораздо худшие ошибки на этом фронте.Во-
zsh
первых, это обычное слово оболочки, которое ожидается, и операторы регулярного выражения в кавычках не влияют на значение операторов регулярного выражения.Соответствует
a|b
регулярному выражению.Это означает, что
=~
можно также добавить к команде[
/test
:(также работает в
yash
. The=~
потребности быть процитированные вzsh
качестве=something
это специальный оператор оболочки есть).Bash 3.1 имел обыкновение вести себя как
zsh
. Он изменился в 3.2, по-видимому, чтобы выровнять сksh93
(хотяbash
была оболочка, которая впервые придумала[[ =~ ]]
), но вы все еще можете сделатьBASH_COMPAT=31
илиshopt -s compat31
вернуться к предыдущему поведению (за исключением того, что, хотя[[ $a =~ a|b ]]
возвращало бы ошибку вbash
3.1, это больше не делает вbash -O compat31
с более новыми версиямиbash
).Надеюсь, это проясняет, почему я сказал, что правила сбивают с толку и почему используют:
помогает в том числе с переносимостью на другие оболочки.
источник
[[ $a = a|b ]]
.a|b
это не оболочка WORD здесь, этоa
,|
иb
маркер. Likeecho a|b
не выводитa|b
или не раскрываетa|b
глобус, вам нужно заключить его в кавычки, так|
как это специальный символ оболочки, который недопустим в этом контексте.[[ $a = (a|b) ]]
будет работать какecho (a|b)
будет работать как(a|b)
оператор подстановки zsh.Стандартные шарики ( «расширение имени файла») являются:
*
,?
, и[ ... ]
.|
не является допустимым оператором glob в стандартных (не extglob) настройках.Пытаться:
источник
|
буквально не вмешиваться? Почему есть синтаксическая ошибка?|
не является оператором glob, поэтому не|
интерпретируется буквально без кавычек? Так почему же синтаксическая ошибка?|
является управляющим персонажем; он никогда не рассматривается как буквальный символ так же, как буква или цифра.[[ $a = a
не является допустимой командой, чей вывод может быть передан другому процессу (по крайней мере, так думала оболочка, которую вы пытались сделать).Если вы хотите соответствие регулярному выражению, тест будет:
источник