Почему удаление цитаты не выполняется между [[...]]?

$ man bash

Разделение слов и расширение имени файла не выполняются над словами между "[[и]]; расширение тильды, расширение параметров и переменных, арифметическое расширение, подстановка команд, замещение процессов и удаление цитат.

$ echo $BASH_VERSION
4.2.10(1)-release

команда 1

$ [[ "hello" =~ "he" ]] && echo YES || echo NO
YES

команда 2

$ [[ "hello" =~ he.* ]] && echo YES || echo NO
YES

команда 3

$ [[ "hello" =~ "he.*" ]] && echo YES || echo NO
NO

Почему команды 2 и 3 отличаются?

3 ответа

Проверьте версию bash. Начиная с версии 3.2 было добавлено это поведение, в котором говорится:

Цитирование аргумента строки для оператора [[command = ~] теперь вынуждает сопоставление строк, как и с другими операторами сопоставления шаблонов.

Я думаю, вы используете bash >= ver 3.2 для своего теста.

В этой причине, когда вы приводите регулярное выражение, он выполняет простые простые сопоставления строк вместо соответствия регулярному выражению.

Обновление: Если вы хотите, чтобы регулярное выражение совпадало с двойными кавычками, используйте:

shopt -s compat31

В соответствии с руководством:

compat31

Если установлено, bash изменяет свое поведение на поведение версии 3.1 в отношении цитируемых аргументов оператору условной команды = ~.

из-за чего ваша команда ведет себя по-другому:

[[ "hello" =~ "he.*" ]] && echo YES || echo NO
YES


Это не то поведение, которое я ожидал бы. Тем не менее, я не верю, что это связано с записью страницы man, которую вы указали, а скорее из-за поведения = ~.

Я предполагаю, что "интерпретируется как буквальный символ в расширенном регулярном выражении.

Например,

[[ hello = "hello" ]] && echo YES || echo NO
YES

Таким образом, двойные кавычки обычно разделяются.

Рассмотрим также grep, на оболочке:

echo foo | grep '"foo"' && echo YES || echo NO

Versus:

echo foo | grep "foo" && echo YES || echo NO
foo
YES

В этом случае "s удаляются оболочкой до того, как grep получит их. В последнем случае grep получает цитату, а механизм регулярных выражений определяет, что это не соответствует.

Я полагаю, что именно это имеет место для = ~.


[[ ... ]] не является синтаксисом POSIX, а расширением, которое находится в оболочке Korn. Bash делает это так, как это делает оболочка Korn, потому что делать это по-другому просто несовместимо ни по какой причине.

Из справочной страницы Korn Shell 93:

Conditional Expressions
A conditional expression is used with the [[ compound command to test attributes of files 
and to compare strings. Field splitting and file name generation are not performed on the 
words between [[ and ]]. Each expression can be constructed from one or more of the 
following unary or binary expressions:

http://www2.research.att.com/sw/download/man/man1/ksh.html

Так почему же оболочка Korn делает это так? 1) Кто заботится; 2) Электронная почта Дейва Корна. 3) Возможно, ответ найден в каком-то документе на http://www.kornshell.com. Но подумайте об этом: если было выполнено разделение поля и расширение файла, как бы эта конструкция отличалась от [ ... ]?

licensed under cc by-sa 3.0 with attribution.