Guide avancé d'écriture des scripts Bash: | ||
---|---|---|
Précédent | Chapitre 16. Redirection d'E/S (entrées/sorties) | Suivant |
Les blocs de code, comme les boucles while, until et for, voire même les blocs de test if/then peuvent aussi incorporer une redirection de stdin. Même une fonction peut utiliser cette forme de redirection (voir Exemple 23-7). L'opérateur < à la fin du bloc de code accomplit ceci.
Exemple 16-4. Boucle while redirigée
#!/bin/bash if [ -z "$1" ] then Fichier=noms.donnees # par défaut, si aucun fichier n'est spécifié. else Fichier=$1 fi #+ Fichier=${1:-noms.donnees} # peut remplacer le test ci-dessus (substitution de paramètres). compteur=0 echo while [ "$nom" != Smith ] # Pourquoi la variable $name est-elle entre guillemets? do read nom # Lit à partir de $Fichier, plutôt que de stdin. echo $nom let "compteur += 1" done <"$Fichier" # Redirige stdin vers le fichier $Fichier. # ^^^^^^^^^^^^ echo; echo "$compteur names read"; echo # Notez que dans certains vieux langages de scripts de shells, #+ la boucle redirigée pourrait tourner dans un sous-shell. # Du coup, $compteur renverrait 0, la valeur initialisée en dehors de la boucle. # Bash et ksh évitent de lancer un sous-shell autant que possible, #+ de façon à ce que ce script, par exemple, tourne correctement. # # Merci à Heiner Steven pour nous l'avoir indiqué. exit 0 |
Exemple 16-5. Autre forme de boucle while redirigée
#!/bin/bash # Ceci est une forme alternative au script précédent. # Suggéré par Heiner Steven #+ comme astuce dans ces situations où une boucle de redirection est lancé #+ comme un sous-shell, et donc que les variables à l'intérieur de la boucle #+ ne conservent pas leurs valeurs une fois la boucle terminée. if [ -z "$1" ] then Fichier=noms.donnees # Par défaut, si aucun fichier spécifié. else Fichier=$1 fi exec 3<&0 # Sauve stdin sur le descripteur de fichier 3. exec 0<"$Fichier" # Redirige l'entrée standard. compteur=0 echo while [ "$nom" != Smith ] do read nom # Lit à partir du stdin redirigé ($Fichier). echo $nom let "compteur += 1" done <"$Fichier" # La boucle lit à partir du fichier $Fichier. # ^^^^^^^^^^^^ exec 0<&3 # Restaure l'ancien stdin. exec 3<&- # Ferme le temporaire fd 3. echo; echo "$compteur noms lus"; echo exit 0 |
Exemple 16-6. Boucle until redirigée
#!/bin/bash # Identique à l'exemple précédent, mais avec une boucle "until". if [ -z "$1" ] then Fichier=noms.donnees # Par défaut, si aucun nom de fichier n'est spécifié. else Fichier=$1 fi # while [ "$nom" != Smith ] until [ "$nom" = Smith ] # Modification de != en =. do read nom # Lit à partir de $Fichier, plutôt que de stdin. echo $nom done <"$Fichier" # Redirige stdin vers le fichier $Fichier. # ^^^^^^^^^^^^ # Même résultats qu'avec la boucle "while" du précédent exemple. exit 0 |
Exemple 16-7. Boucle for redirigée
#!/bin/bash if [ -z "$1" ] then Fichier=noms.donnees # Par défaut, si aucun fichier n'est spécifié. else Fichier=$1 fi compteur_lignes=`wc $Fichier | awk '{ print $1 }'` # Nombre de lignes du fichier cible. # # Très peu naturel, néanmoins cela montre qu'il est possible de rediriger #+ stdin à l'intérieur d'une boucle "for"... #+ si vous êtes assez intelligent. # # Une autre façon plus concise compteur_lignes=$(wc < "$Fichier") for nom in `seq $compteur_lignes` # Rappelez-vous que "seq" affiche une séquence de nombres. # while [ "$nom" != Smith ] -- plus compliqué qu'une boucle "while" -- do read nom # Lit à partir de $Fichier, plutôt que de stdin. echo $nom if [ "$nom" = Smith ] # A besoin de tout ce bagage supplémentaire ici. then break fi done <"$Fichier" # Redirige stdin vers le fichier $Fichier. # ^^^^^^^^^^^^ exit 0 |
Nous pouvons modifier le précédent exemple pour aussi rediriger la sortie de la boucle.
Exemple 16-8. Rediriger la boucle for (à la fois stdin et stdout)
#!/bin/bash if [ -z "$1" ] then Fichier=noms.donnees # Par défaut, si aucun fichier n'est spécifié. else Fichier=$1 fi FichierSauvegarde=$Fichier.nouveau # Fichier où sauvegarder les résultats. NomFinal=Jonah # Nom par lequel terminer la lecture. nb_lignes=`wc $Fichier | awk '{ print $1 }'` # Nombre de lignes du fichier cible. for nom in `seq $nb_lignes` do read nom echo "$nom" if [ "$nom" = "$NomFinal" ] then break fi done < "$Fichier" > "$FichierSauvegarde" # Redirige stdin dans $Fichier, # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ et sauvegarde dans le fichier. exit 0 |
Exemple 16-9. Redirigé un test if/then
#!/bin/bash if [ -z "$1" ] then Fichier=noms.donnees # Valeur par défaut, si aucun nom de fichier n'est #+ spécifié. else Fichier=$1 fi VRAI=1 if [ "$VRAI" ] # if true et if : fonctionnent aussi. then read nom echo $nom fi <"$Fichier" # ^^^^^^^^^^^^ # Lit seulement la première ligne du fichier. # Un test "if/then" n'a aucun moyen de faire une itération sauf si il est #+ intégré dans une boucle. exit 0 |
Exemple 16-10. Fichier de données << nom.données >> pour les exemples ci-dessus
Aristotle Belisarius Capablanca Euler Goethe Hamurabi Jonah Laplace Maroczy Purcell Schmidt Semmelweiss Smith Turing Venn Wilson Znosko-Borowski # This is a data file for #+ "redir2.sh", "redir3.sh", "redir4.sh", "redir4a.sh", "redir5.sh". |
Rediriger stdout d'un bloc de code a le même effet que den sauver la sortie dans un fichier. Voir Exemple 3-2.
Les documents en ligne sont un cas spécial pour la redirection de blocs de code.
Précédent | Sommaire | Suivant |
Utiliser exec | Niveau supérieur | Applications |