Perché while [0] va in loop infinito?


23

Vedo lo stesso comportamento per il ciclo sottostante del ciclo con while [ 1 ]. Perchè è così?

while [ 0 ]; do
    echo "hello"
done

Risposte:


33

Le parentesi quadre singole nella shell sono sinonimo di test(comando separato o shell incorporato), quindi [ 0 ]significano la stessa cosa di test 0. testserve 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é 0o 1sono 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 falsecon 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.


1
Ri: "Quando non viene data un'espressione che assomiglia a un confronto, un test di file o una delle altre operazioni che può fare, ha semplicemente successo": Non penso che sia un buon modo per dirlo. Dopotutto, [ ](senza argomento) e [ "" ](con un solo argomento vuoto) non riescono.
Ruakh,

3
Come spiega @ruakh, questa affermazione è sbagliata: quando non viene data un'espressione che assomiglia a un confronto, un test di file o una delle altre operazioni che può fare, ha semplicemente successo. Qualsiasi singolo argomento da testare (qualsiasi singolo argomento all'interno delle parentesi quadre) viene considerato VERO se l'argomento non è una stringa vuota e entrambi 0e 1non 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.
Ian D. Allen,

Aspetti positivi, ho apportato una correzione.
wingedsubmariner,

10

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 Ae Bcontengono stringhe che sembrano numeri decimali, vengono confrontate come numeri e se Aè maggiore di B, il ciclo viene eseguito. Supponiamo quindi che UNDER_NUCLEAR_ATTACKnon 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 ...

-1

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.

http://www.tldp.org/LDP/abs/html/testconstructs.html


5
Sì, ma non per il motivo per cui sembri pensare. Se [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.
Kevin,

-1

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

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.