Sembra che qui ci siano dei malintesi sull'integrato di Bash true
e, più specificamente, su come Bash espande e interpreta le espressioni tra parentesi.
Il codice in risposta di Miku non ha assolutamente nulla a che fare con il builtin Bash true
, né /bin/true
, né alcun altro sapore del true
comando. In questo caso, true
non è altro che una semplice stringa di caratteri e non true
viene mai effettuata alcuna chiamata al comando / builtin, né dall'assegnazione delle variabili, né dalla valutazione dell'espressione condizionale.
Il seguente codice è funzionalmente identico al codice nella risposta del miku:
the_world_is_flat=yeah
if [ "$the_world_is_flat" = yeah ]; then
echo 'Be careful not to fall off!'
fi
L' unica differenza qui è che i quattro caratteri che vengono confrontati sono 'y', 'e', 'a' e 'h' invece di 't', 'r', 'u' ed 'e'. Questo è tutto. Non è stato fatto alcun tentativo di chiamare un comando o un builtin chiamato yeah
, né (nell'esempio di miku) non c'è alcun tipo di gestione speciale in corso quando Bash analizza il token true
. È solo una stringa, e completamente arbitraria.
Aggiornamento (19-02-2014): dopo aver seguito il link nella risposta di Miku , ora vedo da dove proviene parte della confusione. La risposta di Miku usa parentesi singole, ma lo snippet di codice a cui si collega non usa parentesi. È appena:
the_world_is_flat=true
if $the_world_is_flat; then
echo 'Be careful not to fall off!'
fi
Entrambi i frammenti di codice si comporteranno allo stesso modo, ma le parentesi cambiano completamente ciò che accade sotto il cofano.
Ecco cosa sta facendo Bash in ogni caso:
Nessuna parentesi:
- Espandi la variabile
$the_world_is_flat
alla stringa "true"
.
- Tentativo di analizzare la stringa
"true"
come comando.
- Trova ed esegui il
true
comando (incorporato o /bin/true
, a seconda della versione di Bash).
- Confronta il codice di uscita del
true
comando (che è sempre 0) con 0. Ricorda che nella maggior parte delle shell, un codice di uscita 0 indica il successo e qualsiasi altra cosa indica il fallimento.
- Dal momento che il codice di uscita è 0 (successo), eseguire l'
if
della dichiarazione then
clausola
Parentesi:
- Espandi la variabile
$the_world_is_flat
alla stringa "true"
.
- Analizza l'espressione condizionale ora completamente espansa, che è della forma
string1 = string2
. L' =
operatore è l' operatore di confronto delle stringhe di bash . Così...
- Fai un confronto tra stringhe su
"true"
e "true"
.
- Sì, le due stringhe erano uguali, quindi il valore del condizionale è vero.
- Eseguire l'
if
della dichiarazione then
clausola.
Il codice senza parentesi funziona, poiché il true
comando restituisce un codice di uscita pari a 0, che indica l'esito positivo. Il codice tra parentesi funziona perché il valore di $the_world_is_flat
è identico alla stringa letterale true
sul lato destro di =
.
Solo per riportare il punto a casa, considera i seguenti due frammenti di codice:
Questo codice (se eseguito con i privilegi di root) riavvierà il tuo computer:
var=reboot
if $var; then
echo 'Muahahaha! You are going down!'
fi
Questo codice stampa semplicemente "Bel tentativo". Il comando reboot non viene chiamato.
var=reboot
if [ $var ]; then
echo 'Nice try.'
fi
Aggiornamento (14-04-2014) Per rispondere alla domanda nei commenti sulla differenza tra =
e ==
: AFAIK, non c'è differenza. L' ==
operatore è un sinonimo specifico di Bash =
e, per quanto ho visto, funzionano esattamente allo stesso modo in tutti i contesti.
Si noti, tuttavia, che sto parlando in particolare degli operatori di confronto di stringhe =
e ==
utilizzati in uno dei test [ ]
o [[ ]]
. Non lo sto suggerendo =
e ==
sono intercambiabili ovunque in bash.
Ad esempio, ovviamente non è possibile eseguire un'assegnazione variabile con ==
, come var=="foo"
(bene tecnicamente puoi farlo, ma il valore di var
sarà "=foo"
, perché Bash non sta vedendo un ==
operatore qui, sta vedendo un =
operatore (assegnazione), seguito da il valore letterale ="foo"
, che diventa "=foo"
).
Inoltre, anche se =
e ==
sono intercambiabili, si dovrebbe tenere a mente che come tali test lavoro non dipende dal fatto che lo si usa all'interno [ ]
o [[ ]]
, e anche sulla necessità o meno gli operandi sono quotati. Puoi leggere ulteriori informazioni al riguardo nella Guida agli script avanzati di Bash: 7.3 Altri operatori di confronto (scorri verso il basso fino alla discussione di =
e ==
).
true
efalse
nel contesto della maggior parte dei frammenti di seguito sono solo stringhe semplici, non ilbash built-ins
!!! Si prega di leggere la risposta di Mike Holt di seguito. (Questo è un esempio in cui una risposta altamente votata e accettata è fonte di confusione per l'IMHO e mette in ombra i contenuti perspicaci nelle risposte meno votate)