Может кто-нибудь объяснить разницу между сценариями bash -eq
и ==
в них?
Есть ли разница между следующим?
[ $a -eq $b ]
и [ $a == $b ]
Это просто ==
используется только тогда, когда переменные содержат числа?
Это наоборот: =
и ==
для сравнения строк, -eq
и для числовых. -eq
находится в той же семье , как -lt
, -le
, -gt
, -ge
и -ne
, если это поможет вам вспомнить , что есть что.
==
это, кстати, башизм. Лучше использовать POSIX =
. В bash они эквивалентны, а в обычном sh =
- единственный гарантированно работающий.
$ a=foo
$ [ "$a" = foo ]; echo "$?" # POSIX sh
0
$ [ "$a" == foo ]; echo "$?" # bash specific
0
$ [ "$a" -eq foo ]; echo "$?" # wrong
-bash: [: foo: integer expression expected
2
(Примечание: цитируйте эти расширения переменных! Не оставляйте двойные кавычки выше.)
Если вы пишете #!/bin/bash
сценарий, я рекомендую использовать [[
вместо него . Удвоенная форма имеет больше возможностей, более естественный синтаксис и меньше ошибок, которые могут вас сбить с толку. Двойные кавычки больше не нужны $a
, например:
$ [[ $a == foo ]]; echo "$?" # bash specific
0
Смотрите также:
[[
в целом, представляет собой кш-изм 1980-х годов, принятый bash (и многими другими оболочками). Это все дело - если у вас есть[[
вообще , то можно смело предположить , что все расширения КШ реализованы вокруг него (fnmatch()
-стиль сопоставление с образцом, ERE регулярные выражения с=~
, и да, подавление строки расщепления и файловой системы подстановка) будет доступный. Поскольку[[
это не POSIX синтаксис в целом, нет дополнительной потери переносимости, если предположить, что функции, с которыми он был создан, будут доступны.[[ $var = $pattern ]]
, если вы хотите , что бы в противном случае можно интерпретировать как шаблон fnmatch вместо этого следует интерпретировать как символьную строку. Строкаfoo
не имеет нелитеральной интерпретации, что делает исключение кавычек полностью безопасным; только если OP хочет сопоставить, скажем,foo*
(со звездочкой как буквальной, не означающей ничего, что может идти после строкиfoo
), нужны кавычки или экранирование.[[
без кавычек являются башизмом (указывающим на то, что это была единственная причина, по которой вы не дали ответ +1).[ ... ]
и двойной знак равенства==
. : - /Это зависит от тестовой конструкции вокруг оператора. Ваши варианты: двойные скобки, двойные фигурные скобки, одинарные фигурные скобки или тест
Если вы используете ((...)) , вы проверяете арифметическое равенство,
==
как в C:(Примечание:
0
означаетtrue
в смысле Unix, а ненулевое значение - неудачный тест)Использование
-eq
внутри двойных скобок является синтаксической ошибкой.Если вы используете [...] (или одинарную скобку) или [[...]] (или двойную скобку), или
test
вы можете использовать один из -eq, -ne, -lt, -le, -gt или -ge как арифметическое сравнение .==
Внутри одинарные или двойные скобки (илиtest
команды) является одним из операторов сравнения строк :Как строковый оператор,
=
эквивалентен==
и обратите внимание на пробелы вокруг=
или==
его обязательные.Хотя вы можете это сделать,
[[ 1 == 1 ]]
или[[ $(( 1+1 )) == 2 ]]
он проверяет равенство строк, а не арифметическое равенство.Таким образом,
-eq
получается результат, который, вероятно, ожидался, что целочисленное значение1+1
равно,2
даже если RH является строкой и имеет конечный пробел:В то время как сравнение строк одного и того же занимает конечное пространство, и поэтому сравнение строк не выполняется:
А ошибочное сравнение строк может дать совершенно неправильный ответ. «10» лексикографически меньше «2», поэтому при сравнении строк возвращается
true
или0
. Так многих укусила эта ошибка:против правильного теста для 10, арифметически меньше 2:
В комментариях возникает вопрос о технической причине, по которой использование целого числа
-eq
в строках возвращает True для строк, которые не совпадают:Причина в том, что Bash не типизирован . По
-eq
этой причине строки интерпретируются как целые числа, если это возможно, включая базовое преобразование:И
0
если Bash думает, что это просто строка:Так
[[ "yes" -eq "no" ]]
эквивалентно[[ 0 -eq 0 ]]
Последнее примечание: многие из специфических для Bash расширений тестовых конструкций не являются POSIX и поэтому не работают в других оболочках. Другие оболочки обычно не поддерживают
[[...]]
и((...))
или==
.источник
[[ "yes" -eq "no" ]]
возвращения True. Как bash переводит эти строки в целые числа, которые можно сравнивать? ;-)[[ "yes" -eq "no" ]]
эквивалентны[[ "yes" -eq 0 ]]
or[[ "yes" -eq "any_noninteger_string" ]]
- All True. Эти-eq
силы целого сравнения."yes"
Интерпретируется как целое число0
; сравнение истинно, если другое целое число равно либо0
или результат строки равен0
.==
в примерах кода и только упоминание (переносимый, стандартизованный)=
внизу.==
является псевдонимом, специфичным для bash,=
и выполняет строковое (лексическое) сравнение вместо числового.eq
это, конечно, числовое сравнение.Наконец, я обычно предпочитаю использовать форму
if [ "$a" == "$b" ]
источник
==
здесь является плохим тоном, так как=
это указано только в POSIX.==
поместите его между[[
и]]
. (И убедитесь, что первая строка вашего скрипта указывает на использование/bin/bash
.)Ребята: Несколько ответов показывают опасные примеры. В примере OP
[ $a == $b ]
специально использовалась подстановка переменных без кавычек (по состоянию на октябрь 17 г.). Для[...]
что является безопасным для струнного равенства.Но если вы собираетесь перечислять такие альтернативы, как
[[...]]
, вы должны также сообщить, что правая часть должна быть процитирована. Если не в кавычках, это совпадение с образцом! (Из справочной страницы bash: «Любая часть шаблона может быть заключена в кавычки, чтобы заставить ее сопоставить ее как строку.»).Здесь, в bash, два утверждения, дающие «да», соответствуют шаблону, остальные три - равенству строк:
источник
[ "$lht" = "$rht" ]
в кавычках, чтобы быть надежным даже для равенства. Если у вас есть файл, созданный с помощьюtouch 'Afoo -o AB'
,[ $lft = $rht ]
вернет true, даже если это имя файла совсем не идентичноAB
.