Операторы равенства Баша ( ==, -eq)
Может кто-нибудь, пожалуйста, объясните разницу между -eq
а также ==
в сценарии Bash?
Есть ли разница между следующим?
[ $a -eq $b ]
а также [ $a == $b ]
Это просто ==
используется только когда переменные содержат числа?
4 ответа
Это наоборот: ==
для сравнения строк, -eq
для числовых. -eq
находится в той же семье, что и -lt
, -le
, -gt
, -ge
, а также -ne
, если это поможет вам вспомнить что есть что.
$ [ a == a ]; echo $?
0
$ [ a -eq a ]; echo $?
-bash: [: a: integer expression expected
2
==
это башизм Форма POSIX это =
, Если важна переносимость к небашевым оболочкам, используйте =
,
Это зависит от тестовой конструкции вокруг оператора. Вы можете выбрать двойные скобки, двойные скобки, одиночные скобки или тест
Если вы используете ((...)), вы проверяете арифметическое равенство с ==
как в C:
$ (( 1==1 )); echo $?
0
$ (( 1==2 )); echo $?
1
(Заметка: 0
средства true
в смысле Unix и ненулевой это неудачный тест)
С помощью -eq
внутри двойных скобок есть синтаксическая ошибка.
Если вы используете [...] (или одиночную скобку) или [[...]] (или двойную скобку), или test
Вы можете использовать одно из -eq, -ne, -lt, -le, -gt или -ge в качестве арифметического сравнения.
$ [ 1 -eq 1 ]; echo $?
0
$ [ 1 -eq 2 ]; echo $?
1
$ test 1 -eq 1; echo $?
0
==
внутри одинарных или двойных скобок (или test
команда) является одним из операторов сравнения строк:
$ [[ "abc" == "abc" ]]; echo $?
0
$ [[ "abc" == "ABC" ]]; echo $?
1
Как строковый оператор, =
эквивалентно ==
и обратите внимание на пробел вокруг =
или же ==
его требуется.
Хотя вы можете сделать [[ 1 == 1 ]]
или же [[ $(( 1+1 )) == 2 ]]
это проверка равенства строк, а не арифметического равенства.
Так -eq
дает результат, вероятно, ожидается, что целочисленное значение 1+1
равно 2
даже если RH является строкой и имеет завершающий пробел:
$ [[ $(( 1+1 )) -eq "2 " ]]; echo $?
0
В то время как сравнение строк одного и того же занимает последний пробел, поэтому сравнение строк завершается неудачно:
$ [[ $(( 1+1 )) == "2 " ]]; echo $?
1
И сравнение ошибочных строк может дать полный неправильный ответ. "10" лексикографически меньше, чем "2", поэтому сравнение строк возвращает true
или же 0
, Так много укушен этой ошибкой:
$ [[ 10 < 2 ]]; echo $?
0
против правильного теста для 10, являющегося арифметически меньше, чем 2:
$ [[ 10 -lt 2 ]]; echo $?
1
В комментариях возникает вопрос о технической причине использования целого числа -eq
on strings возвращает True для не совпадающих строк:
$ [[ "yes" -eq "no" ]]; echo $?
0
Причина в том, что Bash нетипизирован. -eq
заставляет строки интерпретироваться как целые числа, если это возможно, включая базовое преобразование:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
А также 0
если Баш думает, что это просто строка:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
Так [[ "yes" -eq "no" ]]
эквивалентно [[ 0 -eq 0 ]]
Последнее замечание: многие из специфических расширений Bash для тестовых конструкций не относятся к POSIX и поэтому не будут работать в других оболочках. Другие оболочки вообще не поддерживают [[...]]
а также ((...))
или же ==
,
==
специфичный для bash псевдоним =
и он выполняет сравнение строк (лексическое) вместо числового сравнения. eq
будучи числовым сравнением, конечно.
Наконец, я обычно предпочитаю использовать форму if [ "$a" == "$b" ]
Ребята: Несколько ответов показывают опасные примеры. Пример ОП [ $a == $b ]
специально использованная подстановка переменных без кавычек (по состоянию на октябрь 17 года). За [...]
это безопасно для равенства строк.
Но если вы собираетесь перечислять альтернативы, такие как [[...]]
Вы также должны сообщить, что правая сторона должна быть в кавычках. Если не указано, это совпадение! (Со страницы руководства bash: "Любая часть шаблона может быть заключена в кавычки, чтобы его можно было сопоставить как строку.").
Здесь, в bash, два выражения, приводящие к "да", соответствуют шаблону, остальные три - равенству строк:
$ rht="A*"
$ lft="AB"
$ [ $lft = $rht ] && echo yes
$ [ $lft == $rht ] && echo yes
$ [[ $lft = $rht ]] && echo yes
yes
$ [[ $lft == $rht ]] && echo yes
yes
$ [[ $lft == "$rht" ]] && echo yes
$