В чем разница между одинарным и двойным знаком равенства (=) при сравнении оболочек?

В чем разница между одинарным и двойным знаком равенства (=) при сравнении оболочек?

Читал, что для сравнения строк внутри ifнужно использовать двойные квадратные скобки. В некоторых книгах говорится, что сравнение можно сделать с помощью =. Но это работает ==и с .

#!/bin/bash
a="hello"
b="world"
if [[ $a == $b ]];then
    echo "equal"
fi

Есть ли разница между =и ==в сравнении?

решение1

В bash(как в kshтом, откуда bashскопирован этот синтаксис), [[ $a == $b ]]это не сравнение, это сопоставление с образцом. Вам нужно [[ $a == "$b" ]]для сравнения на равенство байт-байт. =то же самое, что и ==в любой оболочке, которая поддерживает [[...]].

[[...]]не является стандартным shсинтаксисом.[ командаявляется стандартным, и стандартсравнениеоператор есть =(хотя некоторые [реализации также распознают ==¹).

Как и в любом аргументе любой команды, расширения переменных должны быть заключены в кавычки, чтобы предотвратитьсплит+глоби пустое удаление (только последнее выполняется в zsh), поэтому:

[ "$a" = "$b" ]

В стандартном варианте shсопоставление с образцом выполняется с помощью case:

case $a in
  ($b) ...
esac

Для полноты картины, другиеравенство-подобныйОператоры, которые вы можете встретить в скриптах оболочки:

  • [ "$a" -eq "$b" ]: стандартный [оператор для сравнения десятичных целых чисел. Некоторые [реализации допускают пробелы вокруг чисел, некоторые допускают произвольные арифметические выражения, но это непереносимо. Переносимо, [ "$(($a))" -eq "$(($b))" ]для этого можно использовать. См. также, [ "$((a == b))" -ne 0 ]что будет стандартным эквивалентом (за исключением того, что в POSIX поведение указано только если $aи $bсодержат целые константы):

  • ((a == b)), из ksh и также найденный в zshи bash, возвращает true, если оценка арифметического выражения, сохраненного в , $aдает то же число, что и $b. Обычно это используется для сравнения чисел. Обратите внимание, что существуют различия между оболочками относительно того, как оцениваются арифметические выражения и какие числа поддерживаются (например, bash и некоторые реализации/версии ksh не поддерживают числа с плавающей точкой или обрабатывают числа с ведущими нулями как восьмеричные).

  • expr "$a" = "$b"выполняет сравнение чисел, если оба операнда распознаются как десятичные целые числа (некоторые допускают пробелы вокруг числа), а в противном случае проверяет, имеют ли два строковых операнда одинаковый порядок сортировки. Это также не сработает для значений $aили $b, которые являются exprоператорами типа (, substr...

  • awk -- 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b": если $aи $bраспознаются как числа (по крайней мере, десятичные целые числа и числа с плавающей точкой, такие как 1.2, -1.5e-4, начальные и конечные пробелы игнорируются, некоторые также распознают шестнадцатеричные, восьмеричные или что-либо, распознаваемое strtod()), то выполняется числовое сравнение. В противном случае, в зависимости от реализации, это либо сравнение строк побайтно, либо, как для exprсравнения strcoll(), то есть, являются ли $aи $bсортируют то же самое.

Смотрите также:


¹ который включает GNU [и [встроенные ksh, bash, yash, некоторые, хотя и не все ash, оболочки на основе zsh, однако следует отметить, что в zsh,=cmdспециальный оператор расширения имени файла(раскрывается в тех же контекстах, что и ~useris), который расширяется до пути соответствующей команды, так что там, если вы не отключите опцию equalsотключения этой функции, вам нужно будет написать ее [ "$a" '==' "$b" ], иначе вы получите ошибку, что =команда не найдена. То же самое для[ "$string" '=~' "$regexp" ]

решение2

В bash они эквивалентны:

[[ $x == "$y" ]]
[[ $x = "$y" ]]
[ "$x" == "$y" ]
[ "$x" = "$y" ]

Первые две переменные $x не обязательно заключать в кавычки. Bash выполняет разбиение слов и расширение пути внутри [, но не внутри [[:

$ x='a b'
$ [ -s $x ]
-bash: [: a: binary operator expected
$ [[ -s $x ]]
$ ls
$ [ a = * ]
-bash: [: a: unary operator expected
$ [[ a = * ]]
$ 

[[ $x = "$y" ]]является сравнением строк, но [[ $x = $y ]]представляет собой выражение сопоставления с образцом:

$ y='a*'; [[ aa = "$y" ]]; echo $?
1
$ y='a*'; [[ aa = $y ]]; echo $?
0

-eq предназначен только для использования с целыми числами:

$ [[ x.x -eq x.x ]]
-bash: [[: x.x: syntax error: invalid arithmetic operator (error token is ".x")
$ x=9; [[ "x" -eq 9 ]]; echo $?
0

Смотрите такжеBashFAQ/031: В чем разница между test, [ и [[ ?.

решение3

Оба оператора =и ==являются операторами. В некоторых языках (например, C) один используется для присвоения значения переменной, а другой — для сравнения значений (результатов арифметических выражений). Фактически, оба оператора являются именно такими внутри арифметической оценки. A $((a=23))— это присвоение, a $((a==23))— арифметическое сравнение.

$ echo "$((a=11)) $((a==23))" "$((a=23))" "$((a==23))"
11 0 23 1

Но внутри тестовых конструкций (всехтести[…]и[[…]]) оба оператора означают одно и то же и выполняют одну и ту же операцию.

Итак, все эти варианты:

test "$a" =  "$b"
   [ "$a" =  "$b" ]
  [[ "$a" =  "$b" ]]
test "$a" == "$b"
   [ "$a" == "$b" ]
  [[ "$a" == "$b" ]]

Являютсяэквивалент внутриБашдля проверки бинарного равенства (переменные в кавычках). Если правая переменная не заключена в кавычки, она может быть интерпретирована как шаблон и сопоставлена ​​соответствующим образом: как шаблон, а не как буквальная строка.

Операторы в кавычках \=и \==также эквивалентны при использовании в test и […]. Но оператор в кавычках \==не работает внутри [[…]].

Для других оболочек результаты различаются (правильный результат должен быть Y -(true false), код выхода, отличный от 0 (true) и 1 (false), сообщается как сбой с помощью ¤). Некоторые оболочки терпят неудачу с помощью - -(код выхода всегда 1).

                     | dash  ksh   bash  zsh   
  test a  =  "$b"    | Y -   Y -   Y -   Y -    
     [ a  =  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a  =  "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a  == "$b"    | ¤ ¤   Y -   Y -   - -    
     [ a  == "$b" ]  | ¤ ¤   Y -   Y -   - -    
    [[ a  == "$b" ]] | ¤ ¤   Y -   Y -   Y -    
  test a \=  "$b"    | Y -   Y -   Y -   Y -    
     [ a \=  "$b" ]  | Y -   Y -   Y -   Y -    
    [[ a \=  "$b" ]] | ¤ ¤   Y -   - -   - -    
  test a \== "$b"    | ¤ ¤   Y -   Y -   Y -    
     [ a \== "$b" ]  | ¤ ¤   Y -   Y -   Y -    
    [[ a \== "$b" ]] | ¤ ¤   Y -   - -   - -

Все параметры работают в ksh, операторы в кавычках не работают в bash и zsh (внутри [[…]]), а операторы без кавычек \=и \==также не работают в zsh (вне [[…]]).

Связанный контент