Почему условия Bash не симметричны при использовании подстановочных знаков? - PullRequest
5 голосов
/ 30 мая 2020

Предположим, у меня есть следующий фрагмент Bash:

if [[ "$foo" == *"$bar"* ]] ; then
  echo 'condition is true'
fi

На английском языке sh вы можете описать приведенный выше код с помощью: if bar - это подстрока foo тогда ...

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

if [[ *"$bar"* == "$foo" ]] ; then
  echo 'condition is true'
fi

Возможно, я неправильно понял когда оценивается подстановочный знак?

Ответы [ 2 ]

10 голосов
/ 30 мая 2020

Это явное дизайнерское решение. Здесь man bash:

Когда используются операторы == и! =, Строка справа от оператора считается шаблоном и сопоставляется в соответствии с описанными правилами

Расширение имени пути не выполняется в [[ .. ]], поэтому обычные правила вокруг этого не применяются.

Обработка обоих как шаблона было бы довольно странным. Должно ли [[ a* == [a]* ]] быть истинным, потому что правый шаблон соответствует левой строке, ложным, потому что левый шаблон не соответствует правой строке, или истинным, потому что оба шаблона соответствуют одному и тому же набору строк?

1 голос
/ 30 мая 2020

Оператор сравнения == в двойных скобках ведет себя по-разному:

[[ $foo == 0* ]]   # True if $foo starts with foo "0" (wildcard matching).
[[ $foo == "0" ]] # True if $foo is equal to 0* (literal matching).

Это работает, потому что встроенный оператор [[ bash обрабатывает правую часть теста == как образец:

Когда используются операторы == и !=, строка справа от оператора используется как> образец, и выполняется сопоставление с образцом.

встроенные тесты test, равны ли строки, синтаксис [[expression]] добавляет сравнительный тест для строковых операторов, операторы > и < сравнивают строки для oder (i.e :"aa" < "bb"). оператор проверяет соответствие шаблону, а не только равенство [[ string = pattern ]] истинно, если строка соответствует шаблону, этот оператор не является симметричным, шаблон должен появляться справа от знака равенства, т.е. [[ foo = a* ]] истинно (= 0), тогда как [[ a* = foo ]] ложно (= 1)

[[ "foo" == f* ]] && echo $? # 0

[[ f* == "foo" ]] && echo $? || echo $? # 1

Почему [[ $foo == $bar ]] истинно, а [[ $bar == $foo ]] ложно?

Оператор == не симметричен . Слева требуется строка, а справа - узор. Однако, если вы сделаете двойные кавычки в правой части, что удалит особое значение символов сопоставления с образцом, тогда это превратится в сравнение строк, так что [[ "$foo" == "bar" ]] и [[ "$bar" == "$foo" ]] эквивалентны.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...