Kann jemand bitte den Unterschied zwischen -eq
und ==
in Bash-Skripten erklären ?
Gibt es einen Unterschied zwischen den folgenden?
[ $a -eq $b ]
und [ $a == $b ]
Wird es einfach ==
nur verwendet, wenn die Variablen Zahlen enthalten?
Es ist umgekehrt: =
und ==
sind für String-Vergleiche, -eq
ist für numerische. -eq
in der gleichen Familie wie -lt
, -le
, -gt
, -ge
, und -ne
, wenn das hilft Sie sich daran erinnern , was was ist.
==
ist übrigens ein Bash-Ismus. Es ist besser, die POSIX zu verwenden =
. In Bash sind die beiden gleichwertig, und in Plain Sh =
ist der einzige, der garantiert funktioniert.
$ 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
(Randnotiz: Zitieren Sie diese variablen Erweiterungen! Lassen Sie die obigen doppelten Anführungszeichen nicht aus.)
Wenn Sie eine gerade schreiben #!/bin/bash
Skript dann empfehle ich mit [[
statt . Die doppelte Form bietet mehr Funktionen, eine natürlichere Syntax und weniger Fallstricke, die Sie stören werden. $a
Zum einen sind keine doppelten Anführungszeichen mehr erforderlich :
$ [[ $a == foo ]]; echo "$?" # bash specific
0
Siehe auch:
[[
als Ganzes ist ein Ksh -Ismus aus den 1980er Jahren, den Bash (und viele andere Shells) angenommen haben. Das ist der springende Punkt - wenn Sie[[
überhaupt , dann kann man mit Sicherheit davon ausgehen , dass alle Erweiterungen um ihn herum (implementiert KSHfnmatch()
-Stil Pattern - Matching, ERE reguläre Ausdrücke mit=~
, und ja, Unterdrückung des String-Splitting und Dateisystem Globbing) werden verfügbar. Da[[
es sich in seiner Gesamtheit um eine Nicht-POSIX-Syntax handelt, gibt es keinen zusätzlichen Portabilitätsverlust bei der Annahme, dass die Funktionen, mit denen es geboren wurde, verfügbar sind.[[ $var = $pattern ]]
, wenn Sie möchten, dass das, was sonst als fnmatch-Muster interpretiert würde, stattdessen als Literalzeichenfolge interpretiert wird. Die Zeichenfolgefoo
ist nicht wörtlich interpretiert, sodass Anführungszeichen völlig sicher sind. Nur wenn das OP beispielsweise übereinstimmen möchtefoo*
(mit dem Sternchen als Literal, was nichts bedeutet, was nach der Zeichenfolge kommen kannfoo
), sind Anführungszeichen oder Escapezeichen erforderlich.[[
zitierte Erweiterungen innerhalb eines Bashismus (was darauf hinweist, dass dies der einzige Grund war, warum Sie der Antwort keine +1 gaben).[ ... ]
und doppeltes Gleichheitszeichen==
. : - /Dies hängt vom Testkonstrukt um den Bediener ab. Ihre Optionen sind doppelte Klammern, doppelte Klammern, einfache Klammern oder Test
Wenn Sie ((...)) verwenden , testen Sie das arithmetische Eigenkapital mit
==
wie in C:(Hinweis:
0
bedeutettrue
im Unix-Sinne und ungleich Null ist ein fehlgeschlagener Test)Die Verwendung
-eq
innerhalb doppelter Klammern ist ein Syntaxfehler.Wenn Sie [...] (oder eine einfache Klammer) oder [...]] (oder eine doppelte Klammer) verwenden oder
test
eine von -eq, -ne, -lt, -le, -gt oder verwenden -ge als arithmetischer Vergleich .Das
==
Innere von einfachen oder doppelten Klammern (odertest
Befehlen) ist einer der Zeichenfolgenvergleichsoperatoren :=
Entspricht als Zeichenfolgenoperator==
dem Leerzeichen=
oder==
dem erforderlichen Leerzeichen und notiert es.Während Sie dies tun können
[[ 1 == 1 ]]
oder[[ $(( 1+1 )) == 2 ]]
es die Zeichenfolgengleichheit testet - nicht die arithmetische Gleichheit.So
-eq
ergibt sich das wahrscheinlich erwartete Ergebnis , dass der ganzzahlige Wert von1+1
gleich ist,2
obwohl die relative Luftfeuchtigkeit eine Zeichenfolge ist und ein nachfolgendes Leerzeichen hat:Während ein String-Vergleich desselben den nachgestellten Platz einnimmt und der String-Vergleich daher fehlschlägt:
Und ein falscher Zeichenfolgenvergleich kann zu einer völlig falschen Antwort führen. '10' ist lexikographisch kleiner als '2', daher gibt ein Zeichenfolgenvergleich
true
oder zurück0
. So viele sind von diesem Fehler gebissen:gegen den korrekten Test für 10, der arithmetisch kleiner als 2 ist:
In Kommentaren gibt es eine Frage des technischen Grundes, warum die Verwendung der Ganzzahl
-eq
für Zeichenfolgen True für Zeichenfolgen zurückgibt, die nicht identisch sind:Der Grund ist, dass Bash untypisiert ist . Dies
-eq
bewirkt, dass die Zeichenfolgen nach Möglichkeit als Ganzzahlen interpretiert werden, einschließlich Basiskonvertierung:Und
0
wenn Bash denkt, dass es nur eine Zeichenfolge ist:Ist
[[ "yes" -eq "no" ]]
also gleichbedeutend mit[[ 0 -eq 0 ]]
Letzter Hinweis: Viele der Bash-spezifischen Erweiterungen der Testkonstrukte sind nicht POSIX und schlagen daher in anderen Shells fehl. Andere Schalen unterstützen
[[...]]
und((...))
oder im Allgemeinen nicht==
.quelle
[[ "yes" -eq "no" ]]
Rückgabe von True. Wie zwingt bash diese Zeichenfolgen zu ganzzahligen Werten, die verglichen werden können? ;-)[[ "yes" -eq "no" ]]
entspricht[[ "yes" -eq 0 ]]
oder[[ "yes" -eq "any_noninteger_string" ]]
- All True. Der-eq
Ganzzahlvergleich der Kräfte. Das"yes"
wird als ganze Zahl interpretiert0
; Der Vergleich ist True, wenn die andere Ganzzahl entweder0
oder das Ergebnis der Zeichenfolge ist0
.==
in den Codebeispielen und erwähnt nur (portabel, standardisiert)=
darunter.==
ist ein bash-spezifischer Alias für=
und führt anstelle eines numerischen Vergleichs einen (lexikalischen) Zeichenfolgenvergleich durch.eq
natürlich ein numerischer Vergleich.Schließlich bevorzuge ich normalerweise das Formular
if [ "$a" == "$b" ]
quelle
==
hier ist eine schlechte Form, wie nur=
von POSIX angegeben.==
setzen Sie es zwischen[[
und]]
. (Und stellen Sie sicher, dass die erste Zeile Ihres Skripts die Verwendung angibt/bin/bash
.)Jungs: Mehrere Antworten zeigen gefährliche Beispiele. In dem Beispiel von OP wurde
[ $a == $b ]
speziell die Substitution nicht zitierter Variablen verwendet (Stand: Bearbeitung vom 17. Oktober). Denn[...]
das ist sicher für die String-Gleichheit.Wenn Sie jedoch Alternativen wie aufzählen möchten
[[...]]
, müssen Sie auch darüber informieren, dass die rechte Seite zitiert werden muss. Wenn nicht zitiert, ist es eine Musterübereinstimmung! (Aus der Bash-Manpage: "Jeder Teil des Musters kann in Anführungszeichen gesetzt werden, um zu erzwingen, dass es als Zeichenfolge abgeglichen wird.")Hier in Bash sind die beiden Anweisungen, die "Ja" ergeben, Mustervergleich, die anderen drei sind Zeichenfolgengleichheit:
quelle
[ "$lht" = "$rht" ]
mit den Zitaten sein , um auch für Gleichheit zuverlässig zu sein. Wenn Sie eine Datei mit erstellt habentouch 'Afoo -o AB'
,[ $lft = $rht ]
wird true zurückgegeben, obwohl dieser Dateiname überhaupt nicht mit identisch istAB
.