Может кто-нибудь объяснить разницу между сценариями bash -eqи ==в них?
Есть ли разница между следующим?
[ $a -eq $b ]
и [ $a == $b ]
Это просто ==используется только тогда, когда переменные содержат числа?
Может кто-нибудь объяснить разницу между сценариями 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
Смотрите также:
[[ $var = $pattern ]], если вы хотите , что бы в противном случае можно интерпретировать как шаблон fnmatch вместо этого следует интерпретировать как символьную строку. Строка fooне имеет нелитеральной интерпретации, что делает исключение кавычек полностью безопасным; только если OP хочет сопоставить, скажем, foo*(со звездочкой как буквальной, не означающей ничего, что может идти после строки foo), нужны кавычки или экранирование.
[[без кавычек являются башизмом (указывающим на то, что это была единственная причина, по которой вы не дали ответ +1).
[ ... ]и двойной знак равенства ==. : - /
Это зависит от тестовой конструкции вокруг оператора. Ваши варианты: двойные скобки, двойные фигурные скобки, одинарные фигурные скобки или тест
Если вы используете ((...)) , вы проверяете арифметическое равенство, ==как в 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в строках возвращает True для строк, которые не совпадают:
$ [[ "yes" -eq "no" ]]; echo $?
0
Причина в том, что Bash не типизирован . По -eqэтой причине строки интерпретируются как целые числа, если это возможно, включая базовое преобразование:
$ [[ "0x10" -eq 16 ]]; echo $?
0
$ [[ "010" -eq 8 ]]; echo $?
0
$ [[ "100" -eq 100 ]]; echo $?
0
И 0если Bash думает, что это просто строка:
$ [[ "yes" -eq 0 ]]; echo $?
0
$ [[ "yes" -eq 1 ]]; echo $?
1
Так [[ "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, два утверждения, дающие «да», соответствуют шаблону, остальные три - равенству строк:
$ 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
$
[ "$lht" = "$rht" ] в кавычках, чтобы быть надежным даже для равенства. Если у вас есть файл, созданный с помощью touch 'Afoo -o AB', [ $lft = $rht ]вернет true, даже если это имя файла совсем не идентично AB.
[[в целом, представляет собой кш-изм 1980-х годов, принятый bash (и многими другими оболочками). Это все дело - если у вас есть[[вообще , то можно смело предположить , что все расширения КШ реализованы вокруг него (fnmatch()-стиль сопоставление с образцом, ERE регулярные выражения с=~, и да, подавление строки расщепления и файловой системы подстановка) будет доступный. Поскольку[[это не POSIX синтаксис в целом, нет дополнительной потери переносимости, если предположить, что функции, с которыми он был создан, будут доступны.