Was ist der Unterschied zwischen einfachen und doppelten Gleichheitszeichen (=) bei Shell-Vergleichen?

Was ist der Unterschied zwischen einfachen und doppelten Gleichheitszeichen (=) bei Shell-Vergleichen?

Lesen Sie, dass wir zum Vergleichen von Zeichenfolgen ifdoppelte eckige Klammern verwenden müssen. In einigen Büchern steht, dass der Vergleich mit durchgeführt werden kann =. Aber es funktioniert ==auch mit dem.

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

Gibt es im Vergleich einen Unterschied zwischen =und ?==

Antwort1

In bash(wie in kshwoher bashdiese Syntax kopiert wurde) [[ $a == $b ]]handelt es sich nicht um einen Vergleich, sondern um einen Mustervergleich. Sie benötigen [[ $a == "$b" ]]einen Byte-für-Byte-Gleichheitsvergleich. =ist dasselbe wie ==in jeder Shell, die unterstützt [[...]].

[[...]]ist keine Standard sh-Syntax. Die[ Befehlist Standard, und der StandardVergleichOperator gibt es =(obwohl einige [Implementierungen auch ==¹ erkennen).

Wie bei jedem Argument eines Befehls müssen Variablenerweiterungen in Anführungszeichen gesetzt werden, um zu verhindernteilen+globusund leeres Entfernen (nur Letzteres wird in durchgeführt zsh), also:

[ "$a" = "$b" ]

Im Standard shwird der Mustervergleich folgendermaßen durchgeführt case:

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

Der Vollständigkeit halber: andereGleichheitsähnlichOperatoren, die Ihnen in Shell-Skripten begegnen können:

  • [ "$a" -eq "$b" ]: Standardoperator [zum Vergleichen von Dezimalzahlen. Einige [Implementierungen erlauben Leerzeichen um die Zahlen herum, andere erlauben beliebige arithmetische Ausdrücke, aber das ist nicht portierbar. Portabel kann man [ "$(($a))" -eq "$(($b))" ]dafür verwenden. Siehe auch, [ "$((a == b))" -ne 0 ]was das Standardäquivalent von wäre (außer dass das Verhalten POSIX-mäßig nur angegeben wird, wenn $aund $bganzzahlige Konstanten enthalten):

  • ((a == b)), von ksh und auch in zshund zu finden bash, gibt true zurück, wenn die Auswertung des in gespeicherten arithmetischen Ausdrucks $adieselbe Zahl ergibt wie die von $b. Normalerweise wird dies zum Vergleichen von Zahlen verwendet. Beachten Sie, dass es zwischen Shells Unterschiede hinsichtlich der Auswertung arithmetischer Ausdrücke und der unterstützten Zahlen gibt (z. B. unterstützen Bash und einige Implementierungen/Versionen von ksh keine Gleitkommazahlen oder behandeln Zahlen mit führenden Nullen als Oktalzahlen).

  • expr "$a" = "$b"führt einen Zahlenvergleich durch, wenn beide Operanden als dezimale Ganzzahlen erkannt werden (einige erlauben Leerzeichen um die Zahl herum), und prüft andernfalls, ob die beiden String-Operanden die gleiche Sortierreihenfolge haben. Es würde auch bei Werten von $aoder fehlschlagen, die Operatoren wie , ... $bsind .expr(substr

  • awk -- 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b": Wenn $aund $bals Zahlen erkannt werden (zumindest dezimale Ganzzahlen und Gleitkommazahlen wie 1,2, -1,5e-4, führende und nachfolgende Leerzeichen werden ignoriert, einige erkennen auch Hexadezimalzahlen, Oktalzahlen oder alles, was von erkannt wird strtod()), wird ein numerischer Vergleich durchgeführt. Andernfalls handelt es sich je nach Implementierung entweder um einen Byte-zu-Byte-String-Vergleich oder wie bei expreinem strcoll()Vergleich, d. h., ob $aund $bgleich sortiert sind.

Siehe auch:


¹ das beinhaltet GNU [und das [Builtin von ksh, bash, yash, einigen wenn auch nicht allen ash-basierten Shells und zsh, beachten Sie jedoch, dass in zsh,=cmdist ein spezieller Dateinamenerweiterungsoperator(erweitert in den gleichen Kontexten wie ~useres ist), das zum Pfad des entsprechenden Befehls erweitert wird. Wenn Sie also die equalsOption zum Deaktivieren dieser Funktion nicht deaktivieren, müssen Sie es dort schreiben, [ "$a" '==' "$b" ]da Sie sonst eine Fehlermeldung erhalten, dass der =Befehl nicht gefunden wurde. Gleiches gilt für[ "$string" '=~' "$regexp" ]

Antwort2

Diese sind in Bash gleichwertig:

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

Die ersten beiden $x-Variablen müssen nicht in Anführungszeichen gesetzt werden. Bash führt Worttrennung und Pfadnamenerweiterung innerhalb von [ durch, aber nicht innerhalb von [[:

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

[[ $x = "$y" ]]ist ein Zeichenfolgenvergleich, aber [[ $x = $y ]]ein Mustervergleichsausdruck:

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

-eq ist nur für die Verwendung mit ganzen Zahlen vorgesehen:

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

Siehe auchBashFAQ/031: Was ist der Unterschied zwischen Test, [ und [[ ?.

Antwort3

Sowohl =als auch ==sind Operatoren. In einigen Sprachen (wie C) wird einer verwendet, um einer Variablen einen Wert zuzuweisen, und der andere, um Werte zu vergleichen (Ergebnis arithmetischer Ausdrücke). Tatsächlich sind beide Operatoren genau das in der arithmetischen Auswertung. A $((a=23))ist eine Zuweisung, a $((a==23))ist ein arithmetischer Vergleich.

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

Aber innerhalb der Testkonstrukte (alleprüfenUnd[…]Und[[…]]) beide Operatoren sollen dasselbe bedeuten und dieselbe Operation ausführen.

Also, alle diese Optionen:

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

SindÄquivalent im InnerenSchlagum binäre Gleichheit zu testen (Variablen in Anführungszeichen). Wenn die rechte Variable nicht in Anführungszeichen steht, kann sie als Muster interpretiert und entsprechend abgeglichen werden: als Muster, nicht als wörtliche Zeichenfolge.

Die in Anführungszeichen gesetzten Operatoren \=und \==sind auch gleichwertig, wenn sie in Test und verwendet werden […]. Aber der in Anführungszeichen gesetzte Operator \==schlägt innerhalb von fehl [[…]].

Bei anderen Shells können die Ergebnisse unterschiedlich ausfallen (das richtige Ergebnis sollte Y -(true false) sein, ein Exitcode ungleich 0 (true) und 1 (false) wird mit als Fehler gemeldet ¤). Einige Shells schlagen mit fehl - -(der Exitcode ist immer 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 -   - -   - -

Alle Optionen funktionieren in ksh, in Anführungszeichen gesetzte Operatoren schlagen in bash und zsh (innerhalb von [[…]]) fehl und die nicht in Anführungszeichen gesetzten \=und \==schlagen auch in zsh (außerhalb von [[…]]) fehl.

verwandte Informationen