J'ai le script suivant qui fonctionne bien:
!/bin/bash
a=12
while [ $a -gt 10 ]
do
echo "$a"
a=$(($a-1))
done
echo "done"
Si j'ajoute la ligne "echo something" au-dessus de "do", je m'attends à voir une erreur de syntaxe dans cette ligne. Il paraît que [ $a -gt 10 ]
est contourné et devient une boucle infinie. Comment est-ce possible?
De le manuel bash :
while
La syntaxe de la commande
while
est:while test-commandes; faire commandes-conséquentes; faitExécutezconsequent-commands
aussi longtemps quetest-commands
a un état de sortie de zéro. Le statut de retour est le statut de sortie de la dernière commande exécutée dansconsequent-commands
, ou zéro si aucun n'a été exécuté.
Remarque: test-commands
, pluriel. Vous pouvez utiliser plusieurs commandes dans le test, et c'est donc une boucle parfaitement valide, avec la liste des commandes [ $a -gt 10 ]; echo "$a"
comme test:
while [ $a -gt 10 ]
echo "$a"
do
a=$(($a-1))
done
Alors que la commande [ $a -gt 10 ]
peut ou non échouer, le echo
réussira (presque) toujours (à moins qu'il ne puisse pas écrire le texte, ou qu'une autre erreur se soit produite), donc le final l'état de sortie des commandes de test sera toujours réussi et la boucle sera toujours exécutée.
De man bash
:
tandis que list-1; faire liste-2; terminé
La commande while exécute en continu la listelist-2
tant que dernière commande dans la listelist-1
renvoie un état de sortie de zéro.
Ce qui implique qu'un list
pourrait contenir plusieurs commandes, ce qu'il fait (séparées principalement par des points-virgules ou des sauts de ligne).
Donc, cela fonctionne parfaitement bien:
#!/bin/bash
a=12
while
echo something
echo "a before test = $a"
[ a -gt 10 ]
do
echo "a after test = $a"
a=$(($a-1))
done
echo "done"
Si la dernière commande avant do
est en écho, le code de sortie que le do reçoit est toujours vrai (0) et la boucle devient infinie.
Ce que les autres réponses ici impliquent mais ne disent pas explicitement, c'est que [
est une commande intégrée, pas une partie syntaxique de l'instruction while
.
Essayez de taper help [
sur votre ligne de commande:
[
:[
arg ...]
Évaluez l'expression conditionnelle.C'est un synonyme de la fonction intégrée "test", mais le dernier argument doit
être un littéral]
, pour correspondre à l'ouverture[
.
Votre script est donc exactement comme:
!/bin/bash
a=12
while test $a -gt 10
do
echo "$a"
a=$(($a-1))
done
echo "done"
Vous changez en:
!/bin/bash
a=12
while test $a -gt 10; echo something
do
echo "$a"
a=$(($a-1))
done
echo "done"
Comme exemple de ceci étant poussé à l'extrême,/usr/bin/tzselect a généralement environ 70 lignes de code entre le while
et le do
de la boucle principale qui comprend des instructions case et la substitution de commande et une seule ligne entre le do
et le done
.
(en tant que note pour compléter d'autres réponses).
L'utilisation de plusieurs commandes dans la liste de conditions est souvent utilisée pour implémenter une boucle similaire à la do { blah; blah; } while (condition)
de C, c'est-à-dire que la condition est vérifiée à la fin de la boucle afin que le code de la boucle soit exécuté au moins une fois.
Dans sh
, vous le feriez comme:
while
blah
blah
condition
do
continue # or :
done
Bien que d'autres approches soient possibles comme:
while true; do
blah
blah
condition || break
done
Ou:
continue=true
while "$continue"; do
blah
blah
condition || continue=false
done
end=false
until "$end"; do
blah
blah
condition || end=true
done