Qual è la differenza tra segni di uguale e doppio (=) nei confronti di shell?


28

Leggi che per confrontare le stringhe all'interno ifdobbiamo usare parentesi quadre doppie. Alcuni libri dicono che il confronto può essere fatto da =. Ma funziona anche con questo ==.

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

C'è una differenza tra =e ==nel confronto?


4
C'è una domanda qui da qualche parte? Se è così, non lo vedo. =è per [. ==è per [[.
Chris Down,

@ChrisDown Questo non è assolutamente vero.
xdavidliu,

@xdavidliu Ti interessa elaborare? Certamente è vero in base a POSIX, che non ha comprensione ==, che è il motivo per cui si dovrebbe utilizzare =(uguaglianza) con [, e ==(pattern matching, con la semantica che sono Citando-aware) con [[. Vedere help testvs help [[.
Chris Down,

@ChrisDown forse sto fraintendendo cosa si intende per "è per". Se "è per" significa "funziona solo con", allora il commento non è vero, poiché [ foo == foo ] && echo foosicuramente stampa foo, indicando che ==funziona con [. Tuttavia, se per "è per" intendi "si intendeva utilizzare", allora ho un'obiezione minore.
xdavidliu,

@xdavidliu "sta per" nel caso specifico in cui stai citando significa "è definito da POSIX". Solo perché bash sembra accettarlo come convenienza, non significa che sia consigliato - se stai comunque evitando la portabilità, usa solo [[in primo luogo che ha una comprensione significativamente più sfumata di tokenizzazione, suddivisione di parole, ecc ...
Chris Down il

Risposte:


28

[[ $a == $b ]]non è un confronto, è una corrispondenza del modello. È necessario [[ $a == "$b" ]]per il confronto di uguaglianza da byte a byte. =è lo stesso ==di qualsiasi shell che supporti [[...]](introdotto da ksh).

[[...]]non è una shsintassi standard . Il [ comando è standard e l' operatore di confronto standard è presente =(anche se alcune [implementazioni lo riconoscono ==).

Proprio come in qualsiasi argomento di qualsiasi comando, le variabili devono essere citate, quindi:

[ "$a" = "$b" ]

In standard sh, la corrispondenza del modello viene eseguita con case:

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

Per completezza, altri operatori simili all'uguaglianza che potresti incontrare negli script di shell:

  • [ "$a" -eq "$b" ]: [operatore standard per confrontare numeri interi decimali. Alcune [implementazioni consentono spazi vuoti attorno ai numeri, altre consentono espressioni aritmetiche arbitrarie, ma questo non è portatile. Portabilmente, si può usare [ "$((a))" -eq "$((b))" ]per quello. Vedi anche [ "$((a == b))" -ne 0 ]quale sarebbe l'equivalente standard (tranne che POSIXly, il comportamento è specificato solo se $ae $bcontiene costanti intere) di:
  • ((a == b)), da ksh e anche trovato in zshe bash, restituisce vero se la valutazione dell'espressione aritmetica memorizzata $aproduce lo stesso numero di quella di $b. In genere, viene utilizzato per confrontare i numeri. Nota che ci sono variazioni tra le shell su come vengono valutate le espressioni aritmetiche e quali numeri sono supportati (ad esempio bash e alcune implementazioni / versioni di ksh non supportano il virgola mobile o trattano i numeri con zeri iniziali come ottali).

  • expr "$a" = "$b"esegue un confronto numerico se entrambi gli operandi sono riconosciuti come numeri interi decimali (alcuni consentono spazi vuoti attorno al numero) e verifica in altro modo se i due operatori di stringa hanno lo stesso ordinamento. Fallirebbe anche per valori di $ao $bche sono exproperatori come (, substr...

  • awk 'BEGIN{exit !(ARGV[1] == ARGV[2])}' "$a" "$b": se $ae $bsono riconosciuti come numeri (almeno numeri interi decimali e in virgola mobile come 1.2, -1.5e-4, ignorando gli spazi vuoti finali iniziali, alcuni riconoscendo anche esadecimali, ottali o qualsiasi cosa riconosciuta da strtod()), viene eseguito un confronto numerico. Altrimenti, a seconda dell'implementazione, è un confronto di stringhe da byte a byte, o come per exprun strcoll()confronto, ovvero se $ae $bordinare lo stesso.

Guarda anche:


13

Questi sono equivalenti in bash:

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

Le prime due variabili $ x non devono essere quotate. Bash esegue la suddivisione delle parole e l'espansione del percorso all'interno di [ma non all'interno di [[:

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

[[ $x = "$y" ]]è un confronto di stringhe ma [[ $x = $y ]]è un'espressione di corrispondenza del modello:

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

-eq è pensato solo per essere usato con numeri interi:

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

Vedi anche BashFAQ / 031: Qual è la differenza tra test, [e [[? .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.