What needs this iteration, woman?
--Shakespeare, Othello
Les opérations sur les blocs de code sont la clé des scripts shell structurés et organisés. Les syntaxes de boucles et de branchements fournissent les outils pour cela.
Une boucle est un bloc de code qui répète [45] une liste de commandes aussi longtemps que la condition de contrôle de la boucle est vraie.
C'est la construction de boucle de base. Elle diffère de façon significative de sa contre-partie en C.
for arg in [liste]
do
commande(s)...
done
À chaque passage dans la boucle, arg prend successivement la valeur de toutes les variables de la liste.
for arg in "$var1" "$var2" "$var3" ... "$varN" # Lors du tour 1 de la boucle, arg = $var1 # Lors du tour 2 de la boucle, arg = $var2 # Lors du tour 3 de la boucle, arg = $var3 # ... # Lors du tour N de la boucle, arg = $varN # Les arguments dans [liste] sont mis entre guillemets pour empêcher une #+ possible séparation des mots.
L'argument liste peut contenir des caractères joker.
Si do est sur la même ligne que for, il est impératif d'avoir un point virgule après la liste.
for arg in [liste] ; do
Chaque élément de la [liste] peut contenir de multiples paramètres. C'est utile pour travailler sur des paramètres en groupe. Dans de tels cas, utilisez la commande set (voir l'Exemple 14.16, « Utiliser set avec les paramètres de position ») pour forcer l'analyse de chaque élément de la [liste] et l'affectation de chaque composant aux paramètres positionnels.
Une variable peut fournir la [liste] dans une boucle for.
Si la [liste] dans une boucle for contient des caractères joker (* et ?) utilisés dans le remplacement des noms de fichier, alors l'expansion des noms de fichiers a lieu.
Omettre la partie in [liste] d'une boucle for fait en sorte que la boucle opère sur $@, les paramètres de position. Une illustration particulièrement intelligente de ceci est l'Exemple A.15, « Générer des nombres premiers en utilisant l'opérateur modulo ». Voir aussi Exemple 14.17, « Inverser les paramètres de position ».
Il est possible d'utiliser la substitution de commandes pour générer la [liste] d'une boucle for. Voir aussi l'Exemple 15.54, « Utiliser seq pour générer l'incrément d'une boucle », l'Exemple 10.10, « Afficher les liens symboliques dans un répertoire » et l'Exemple 15.48, « Conversion de base ».
Voici un exemple un peu plus complexe de l'utilisation de la substitution de commande pour créer la [liste].
Un peu la même chose.
Encore un exemple d'une [liste] résultant d'une substitution de commande.
Un dernier exemple de [list] / substitution de commande, avec cette fois une « commande » qui est une fonction.
genere_liste () { echo "un deux trois" } for mot in $(genere_liste) # "mot" va chercher le résultat de la fonction do echo "$mot" done # un # deux # trois
La sortie d'une boucle for peut être envoyée via un tube à une ou plusieurs commandes.
Le stdout d'une boucle peut être redirigé vers un fichier, comme cette légère modification du précédent exemple le montre.
Il existe une autre syntaxe pour une boucle for ressemblant fortement à celle du C. Elle nécessite des parenthèses doubles.
Voir aussi l'Exemple 26.15, « Application complexe des tableaux Exploration d'une étrange série mathématique », l'Exemple 26.16, « Simuler un tableau à deux dimensions, puis son test » et l'Exemple A.6, « Séries de Collatz ».
---
Maintenant, une boucle for utilisée dans un contexte de la « vie quotidienne ».
Cette construction teste une condition au début de la boucle et continue à boucler tant que la condition est vraie (renvoie un 0 comme code de sortie). Par opposition à une boucle for, une boucle while trouve son utilité dans des situations où le nombre de répétitions n'est pas connu dès le départ.
while [ condition ]
do
commande(s)...
done
La syntaxe avec crochets dans une boucle while n'est rien d'autre que notre vieille connaissance, le test entre crochets utilisé dans un test if/then. En réalité, une boucle while peut de manière tout à fait correcte utiliser la syntaxe plus souple avec doubles crochets (while [[ condition ]]).
Comme c'est le cas avec les boucles for, placer le do sur la même ligne que le test de la condition nécessite un point virgule.
while [ condition ] ; do
Note that the test brackets are not mandatory in a while loop. See, for example, the getopts construct.
Une boucle while peut avoir de multiples conditions. Seule la condition finale détermine quand la boucle se termine. Malgré tout, ceci nécessite une syntaxe de boucle légèrement différente.
Comme pour une boucle for, une boucle while peut employer une syntaxe identique à celle de C, avec les parenthèses doubles (voir aussi l'Exemple 9.33, « Manipulation, à la façon du C, de variables »).
À l'intérieur des crochets de test, une boucle while peut appeler une fonction.
t=0 condition () { ((t++)) if [ $t -lt 5 ] then return 0 # true else return 1 # false fi } while condition # ^^^^^^^^^ # Appel de fonction -- quatre itérations de boucle. do echo "Toujours en cours : t = $t" done # Toujours en cours : t = 1 # Toujours en cours : t = 2 # Toujours en cours : t = 3 # Toujours en cours : t = 4
En couplant la puissance de la commande read avec une boucle while, nous obtenons la syntaxe while read, qui s'avère bien utile pour lire et analyser des fichiers.
cat $nomfichier | # Fournit des informations à partir d'un fichier. while read ligne # Tant qu'il y a une nouvelle ligne à lire... do ... done # =========== Snippet from "sd.sh" example script ========== # while read value # Read one data point at a time. do rt=$(echo "scale=$SC; $rt + $value" | bc) (( ct++ )) done am=$(echo "scale=$SC; $rt / $ct" | bc) echo $am; return $ct # This function "returns" TWO values! # Caution: This little trick will not work if $ct > 255! # To handle a larger number of data points, #+ simply comment out the "return $ct" above. } <"$datafile" # Feed in data file.
Une boucle while peut avoir son entrée stantard redirigée vers un fichier par un < à la fin.
Une boucle while peut avoir son entrée standard (stdin) fourni via un tube.
Cette construction teste une condition au début de la boucle et continue à boucler tant que la condition est fausse (le contraire de la boucle while).
until [ condition-est-vraie ]
do
commande(s)...
done
Notez qu'une boucle until teste la condition de fin au début de la boucle, contrairement aux constructions similaires dans certains langages de programmation.
Comme pour les boucles for, placer do sur la même ligne que le test de la condition nécessite un point virgule.
until [ condition-est-vraie ] ; do
Comment choisir entre une boucle for, une boucle while et une boucle until ? En C, vous utiliserez typiquement une boucle for quand le nombre d'itérations est déjà connu. Néanmoins, avec Bash, la situation est plus compliquée. La boucle for en Bash est moins structurée et plus flexible que son équivalent dans d'autres langages. Du coup, n'hésitez pas à utiliser le type de boucle qui vous permet de faire ce que vous souhaitez de la façon la plus simple.
[45] Itération : exécution répétée d'une commande ou d'un groupe de commandes, en général -- mais pas toujours, tant qu' une certaine condition reste vraie ou jusqu'à ce qu' une certaine condition devienne vraie.