Operatori di uguaglianza di Bash (==, -eq)

Qualcuno può spiegare la differenza tra -eq e == in bash scripting?

C’è qualche differenza tra quanto segue?

[ $a -eq $b ] e [ $a == $b ]

È semplicemente che == è usato solo quando le variabili contengono numeri?

È il contrario: == è per i confronti tra stringhe, -eq è per quelli numerici. -eq appartiene alla stessa famiglia di -le , -le , -le , -ge e -ne , se questo ti aiuta a ricordare quale è quale.

 $ [ a == a ]; echo $? 0 $ [ a -eq a ]; echo $? -bash: [: a: integer expression expected 2 

== è un bash-ismo. Il modulo POSIX è = . Se la portabilità alle shell non bash è importante, utilizzare = .

== è un alias specifico per bash per = ed esegue un confronto stringa (lessicale) invece di un confronto numerico. eq essendo un confronto numerico ovviamente.

Infine, di solito preferisco usare il modulo if [ "$a" == "$b" ]

Dipende dal Test costrutto attorno all’operatore. Le opzioni disponibili sono doppie parentesi, doppie parentesi, singole parentesi o test

Se usi ((…)) , stai testando l’equity aritmetica con == come in C:

 $ (( 1==1 )); echo $? 0 $ (( 1==2 )); echo $? 1 

(Nota: 0 significa true nel senso Unix e non zero è un test fallito)

L’uso di -eq all’interno della doppia parentesi è un errore di syntax.

Se stai usando […] (o una sola parentesi) o [[…]] (o doppia parentesi), o test puoi usare uno di -eq, -ne, -lt, -le, -gt, o -ge come confronto aritmetico .

 $ [ 1 -eq 1 ]; echo $? 0 $ [ 1 -eq 2 ]; echo $? 1 $ test 1 -eq 1; echo $? 0 

Il valore == all’interno di parentesi graffe singole o doppie (o comando test ) è uno degli operatori di confronto stringhe :

 $ [[ "abc" == "abc" ]]; echo $? 0 $ [[ "abc" == "ABC" ]]; echo $? 1 

Come operatore stringa, = è equivalente a == e nota lo spazio bianco intorno = o == richiesto.

Mentre puoi fare [[ 1 == 1 ]] o [[ $(( 1+1 )) == 2 ]] sta testando l’uguaglianza delle stringhe – non l’uguaglianza aritmetica.

Quindi -eq produce il risultato che probabilmente il valore intero di 1+1 è uguale a 2 anche se l’RH è una stringa e ha uno spazio finale:

 $ [[ $(( 1+1 )) -eq "2 " ]]; echo $? 0 

Mentre un confronto tra stringhe dello stesso preleva lo spazio finale e quindi il confronto tra stringhe fallisce:

 $ [[ $(( 1+1 )) == "2 " ]]; echo $? 1 

E un confronto di stringhe errato può produrre la risposta sbagliata completa. ’10’ è lessicograficamente inferiore a ‘2’, quindi un confronto di stringhe restituisce true o 0 . Così tanti sono morsi da questo bug:

 $ [[ 10 < 2 ]]; echo $? 0 

vs il test corretto per 10 essendo aritmeticamente inferiore a 2:

 $ [[ 10 -lt 2 ]]; echo $? 1 

Nei commenti, c'è una domanda sulla ragione tecnica che usa l'intero -eq sulle stringhe restituisce Vero per le stringhe che non sono le stesse:

 $ [[ "yes" -eq "no" ]]; echo $? 0 

Il motivo è che Bash non è tipizzato . L' -eq consente di interpretare le stringhe come numeri interi, se ansible, inclusa la conversione di base:

 $ [[ "0x10" -eq 16 ]]; echo $? 0 $ [[ "010" -eq 8 ]]; echo $? 0 $ [[ "100" -eq 100 ]]; echo $? 0 

E 0 se Bash pensa che sia solo una stringa:

 $ [[ "yes" -eq 0 ]]; echo $? 0 $ [[ "yes" -eq 1 ]]; echo $? 1 

Quindi [[ "yes" -eq "no" ]] è equivalente a [[ 0 -eq 0 ]]

Ultima nota: molte delle estensioni specifiche di Bash ai costrutti di test non sono POSIX e quindi falliranno in altre shell. Altre shell generalmente non supportano [[...]] e ((...)) o == .

Ragazzi: diverse risposte mostrano esempi pericolosi. Esempio di OP [ $a == $b ] usato in modo specifico per sostituzione di variabili non quotate (a partire dalla modifica di ottobre ’17). Per [...] questo è sicuro per l’uguaglianza delle stringhe.

Ma se hai intenzione di enumerare alternative come [[...]] , devi anche informare che il lato destro deve essere citato. Se non citato, è un abbinamento di pattern! (Dalla pagina man di bash: “Qualunque parte del pattern può essere citata per forzare la corrispondenza con una stringa.”).

Qui in bash, le due dichiarazioni che producono “sì” sono la corrispondenza del modello, altre tre sono l’uguaglianza delle stringhe:

 $ 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 $