2013-03-20 9 views
35

Sto cercando di ottenere un semplice ciclo while che funzioni in bash che utilizza due condizioni, ma dopo aver provato molte sintassi diverse da vari forum, non riesco a smettere di lanciare un errore. Ecco quello che ho:Bash scripting, più condizioni nel ciclo while

while [ $stats -gt 300 ] -o [ $stats -eq 0 ] 

Ho anche provato:

while [[ $stats -gt 300 ] || [ $stats -eq 0 ]] 

... così come molti altri costrutti. Voglio che questo ciclo continui mentre $stats is > 300 o se $stats = 0.

risposta

81

Le opzioni corrette sono (in ordine di raccomandazione crescente):

# Single POSIX test command with -o operator (not recommended anymore). 
# Quotes strongly recommended to guard against empty or undefined variables. 
while [ "$stats" -gt 300 -o "$stats" -eq 0 ] 

# Two POSIX test commands joined in a list with ||. 
# Quotes strongly recommended to guard against empty or undefined variables. 
while [ "$stats" -gt 300 ] || [ "$stats" -eq 0 ] 

# Two bash conditional expressions joined in a list with ||. 
while [[ $stats -gt 300 ]] || [[ $stats -eq 0 ]] 

# A single bash conditional expression with the || operator. 
while [[ $stats -gt 300 || $stats -eq 0 ]] 

# Two bash arithmetic expressions joined in a list with ||. 
# $ optional, as a string can only be interpreted as a variable 
while ((stats > 300)) || ((stats == 0)) 

# And finally, a single bash arithmetic expression with the || operator. 
# $ optional, as a string can only be interpreted as a variable 
while ((stats > 300 || stats == 0)) 

Alcune note:

  1. citando le espansioni dei parametri all'interno [[ ... ]] e ((...)) è facoltativo; se la variabile non è impostata, -gt e -eq assumerà un valore 0.

  2. utilizzando $ è facoltativo all'interno ((...)), ma il suo utilizzo può evitare errori involontari. Se stats non è impostato, allora ((stats > 300)) assumerà stats == 0, ma (($stats > 300)) genererà un errore di sintassi.

+0

Risposta fantastica, straordinariamente accurata – jake9115

+0

Bravo. un modo classico per rispondere a un post. Molto bene. Suppongo che tu possa usare la stessa sintassi anche con 'until', sì? – SaxDaddy

+0

@SaxDaddy Più o meno, fintanto che si presta attenzione a negare correttamente le condizioni: 'mentre [foo -o bar]' diventa 'until! [foo -o bar] ', ma' while foo || bar' diventa 'until! foo &&! bar'. – chepner

1

Prova:

while [ $stats -gt 300 -o $stats -eq 0 ] 

[ è una chiamata a test. Non è solo per il raggruppamento, come le parentesi in altre lingue. Controllare man [ o man test per ulteriori informazioni.

+1

Raccomando '[[' oltre '['. Vedi il mio commento sull'altra risposta. – danfuzz

+0

È giusto. Ho usato [] perché era quello che l'OP stava cercando di usare. Ho visto entrambi usati con successo. – drewmm

0

L'extra [] sulla parte esterna della seconda sintassi non è necessaria e può essere fonte di confusione. Puoi usarli, ma se devi devi avere uno spazio bianco tra di loro.

alternativa:

while [ $stats -gt 300 ] || [ $stats -eq 0 ] 
+0

In realtà, '[[' è generalmente il preferito incorporato per introdurre un'espressione di test. Ha diversi vantaggi rispetto alla vecchia sintassi '['. – danfuzz