La sintassi della shell è fortemente dipendente dal contesto. Cioè, che cosa particolare (come true
o false
) significa che dipende molto da dove si verifica. Nei tuoi esempi, false
ha tre significati completamente diversi:un comando, un valore stringa e un nome di variabile (inesistente) contenente un valore intero. Fammi scorrere gli esempi:
-
false
come comando:false; echo $? # prints "1" if false; then echo "yep"; else echo "nope"; fi # prints "nope"
C'è un comando chiamato "false" (generalmente /usr/bin/false, o un builtin bash che fa la stessa cosa) che in realtà non fa altro che uscire con uno stato di errore. Come stato di uscita, zero indica il successo (che è una specie di verità) e diverso da zero indica il fallimento (che è una specie di falso). Questo è l'opposto della più comune convenzione zero=false, nonzero=true, ma per gli exit status ha più senso.
-
false
come valore stringa non interpretato:if [[ false ]]; then echo "yep"; else echo "nope"; fi # prints "yep" if [[ true ]]; then echo "yep"; else echo "nope"; fi # prints "yep" if [[ wibble ]]; then echo "yep"; else echo "nope"; fi # prints "yep" if [[ "this is a string" ]]; then echo "yep"; else echo "nope"; fi # prints "yep" [[ false ]]; echo $? # prints "0" (=success) [ false ]; echo $? # prints "0" (=success) test false; echo $? # prints "0" (=success)
In tutti questi casi, il comando
test
o il suo sinonimo[
o l'espressione condizionale bash[[ ]]
non ha ottenuto un'espressione, solo una singola stringa, quindi eseguono un test molto semplice:è una stringa di lunghezza diversa da zero? "true", "false", "wibble", ecc. sono tutti di lunghezza diversa da zero, quindi il comando/espressione è simile alla verità, quindi ha successo. Confronta con:[[ "" ]]; echo $? # prints "1" (=failure), because the string is zero-length [[ ]]; echo $? # prints "1" (=failure), because there isn't even a string [ ]; echo $? # same
Nota che
test
e[
sono comandi normali e "false" (e "wibble" ecc.) è solo un argomento.[[ ]]
è un po' di sintassi bash che può essere usata al posto di un comando. I loro argomenti/contenuti vengono analizzati in modo diverso dai nomi dei comandi stessi. -
false
come possibile nome di variabile che potrebbe contenere un numero intero:if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi # prints "equal"
Questo è un po' più strano e dipende dai dettagli di come
[[ ]]
di bash test di uguaglianza numerica. Nota che in[[ ]]
(e[ ]
etest
espressioni),-eq
verifica l'uguaglianza numerica e=
test per l'uguaglianza delle stringhe. Quindi, ad esempio,[[ 01 -eq 1 ]]
(poiché 1 e 01 sono numericamente uguali) è vero, ma[[ 01 = 1 ]]
è falso (perché non sono la stessa stringa). Nel caso di[[ false -eq true ]]
, "true" e "false" non sono valori interi, quindi bash cerca di convertirli in numeri interi trattandoli come nomi di variabili (e sperando che le variabili contengano valori interi). In effetti, nessuno dei due è definito come variabile, quindi entrambi valutano la stringa vuota, che può essere interpretata come il numero intero 0. Osserva:if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi # prints "equal" if [[ false -eq 0 ]]; then echo "equal"; else echo "nope"; fi # prints "equal" false=5 if [[ false -eq true ]]; then echo "equal"; else echo "nope"; fi # now prints "nope"
Nota che la definizione di
false
come variabile non ha alcun effetto sui suoi altri usi; quando usato come comando uscirà comunque con lo stato 1, e quando usato come stringa è ancora solo "false" (non "5").