Яка різниця між одинарними та подвійними рівними знаками (=) у порівняннях оболонок?


28

Прочитайте, що для порівняння рядків всередині ifнам потрібно використовувати подвійні квадратні дужки. У деяких книгах сказано, що порівняння можна зробити за допомогою =. Але це ==теж працює.

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

Чи є різниця між порівнянням =та ==у порівнянні?


4
Десь тут є питання? Якщо так, я цього не бачу. =є для [. ==є для [[.
Кріс Даун

@ChrisDown Це абсолютно неправда.
xdavidliu

@xdavidliu Догляд докласти? Це, безумовно , вірно згідно з POSIX, який не має розуміння ==, саме тому вам слід використовувати =(рівність) з [(та ==узгодження шаблону, із семантикою , котра цитує) [[. Див help testпроти help [[.
Кріс Даун

@ChrisDown, можливо, я неправильно розумію, що розуміється під "для". Якщо "є для" означає "працює лише з", то коментар не відповідає дійсності, оскільки, [ foo == foo ] && echo fooбезумовно, друкує foo, вказуючи на те, що ==працює з [. Однак, якщо під "є для" ви маєте на увазі "було призначено для використання з", я маю менше заперечень.
xdavidliu

@xdavidliu "призначено для" у конкретному випадку, який ви згадуєте, "визначено POSIX". Тільки тому, що bash трапляється сприймати це як зручність, не означає, що це рекомендується - якщо ви все-таки відмовляєтесь від переносимості, просто використовуйте [[в першу чергу, що має значно більш нюансоване розуміння токенізації, розбиття слів тощо ...
Chris Down

Відповіді:


28

[[ $a == $b ]]це не порівняння, це відповідність шаблонів. Вам потрібно [[ $a == "$b" ]]для порівняння рівності байт-байт. =такий же, як ==у будь-якій оболонці, яка підтримує [[...]](вводиться ksh).

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

Як і в будь-якому аргументі будь-якої команди, змінні повинні бути цитовані, так що:

[ "$a" = "$b" ]

У стандартній shформі відповідність візерунка здійснюється за допомогою case:

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

Для повноти інших операторів, подібних рівності, ви можете зіткнутися в скриптах оболонки:

  • [ "$a" -eq "$b" ]: стандартний [оператор для порівняння десяткових цілих чисел. Деякі [реалізації дозволяють пробілами навколо чисел, деякі допускають довільні арифметичні вирази, але це не є портативним. Портативно, [ "$((a))" -eq "$((b))" ]для цього можна скористатися . Дивіться також, [ "$((a == b))" -ne 0 ]що було б стандартним еквівалентом (за винятком POSIXly, поведінка задається лише, якщо $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начебто те ж саме.

Дивись також:


13

Вони еквівалентні в 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: Яка різниця між тестом, [та [[? .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.