Операторы равенства Баша ( ==, -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
$
Другие вопросы по тегам