Risposte:
Le parentesi quadre singole nella shell sono sinonimo di test
(comando separato o shell incorporato), quindi [ 0 ]
significano la stessa cosa di test 0
. test
serve per fare confronti e testare gli attributi dei file, come puoi leggere nella sua pagina man. Quando non viene fornita un'espressione che assomiglia a un confronto, a un test di file o a una delle altre operazioni che può fare, testerà invece se l'argomento è presente e una stringa non vuota. Né 0
o 1
sono input davvero appropriati per il test, e poiché il test delle stringhe non vuote ha semplicemente successo e il ciclo while viene ripetuto per sempre.
Potresti voler provare invece
while false; do
echo "hello"
done
eventualmente sostituendo false
con true
. O forse quello che vuoi è usare (( ))
:
while (( 0 )); do
echo "hello"
done
Che si comporterà come la maggior parte delle lingue, dove 0 significa fallimento / falso e 1 significa successo / vero.
0
e 1
non sono stringhe vuote. I nuovi programmatori di shell spesso scrivono if [ 1=2 ]
invece di if [ 1 = 2 ]
e si chiedono perché il primo sia sempre vero. È vero perché è un singolo argomento e non è una stringa vuota.
Il valore 0 qui non agisce come una costante numerica, ma come una stringa di caratteri. Questi test sono tutti equivalenti nel loro effetto di produrre uno stato di terminazione di successo:
[ A ]
[ "XYZ" ]
[ 0 ]
questi producono uno stato di terminazione non riuscito:
[ ]
[ "" ]
c'è un argomento non vuoto, che valuta come vero logico. Questo ti permette di fare cose come:
if [ $UNDER_NUCLEAR_ATTACK ] ; then
launch-missiles -a $DRY_RUN # $DRY_RUN set to "-n" during testing
fi
La variabile UNDER_NUCLEAR_ATTACK
è impostata su qualsiasi valore non vuoto per indicare vero oppure non è impostata o vuota per indicare falso.
Possiamo applicare l' !
operatore per invertire la logica:
[ ! a ] # fails: a is nonblank so true; and not true is false.
[ ! ] # succeeds: blank is false, not blank is true.
Per valutare una condizione numerica, è necessario utilizzare operatori di test numerici:
while [ $A -gt $B ] ; do ...
Se A
e B
contengono stringhe che sembrano numeri decimali, vengono confrontate come numeri e se A
è maggiore di B
, il ciclo viene eseguito. Supponiamo quindi che UNDER_NUCLEAR_ATTACK
non sia un valore booleano di tipo stringa vuoto o non vuoto, ma in realtà un valore booleano numerico che sia 0
(falso) o un altro valore (vero). In tal caso, scriveremmo il test in questo modo:
if [ $UNDER_NUCLEAR_ATTACK -ne 0 ] ; then ...
Un costrutto if / then verifica se lo stato di uscita di un elenco di comandi è 0 (poiché 0 significa "successo" per convenzione UNIX) e, in tal caso, esegue uno o più comandi.
In breve, stai restituendo un risultato del test pari a zero.
[
ottiene solo un argomento (escluso ]
ovviamente), esce con stato zero se l'argomento non è vuoto, diverso da zero se lo è. Quindi, per esempio, [ 1 ]
restituirà anche un codice di uscita di 0
.
Il valore 0 è considerato vero per il ciclo while, quindi la condizione per il ciclo while è vera e quindi continua a mostrare il ciclo infinito. È vero se sostituiamo 0 con 1, poiché qualsiasi numero intero che scriviamo tra la condizione restituirà vero
[ ]
(senza argomento) e[ "" ]
(con un solo argomento vuoto) non riescono.