IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Introduction à la programmation en Bash


précédentsommairesuivant

VIII. Structures de contrôle case et while

VIII-1. Choix multiple case

Syntaxe :

 
Sélectionnez
case mot in
[ modèle [ | modèle ] ... ) suite_de_commandes ;; ] ...
esac

Le shell évalue la valeur de mot puis compare séquentiellement cette valeur à chaque modèle. Dès qu'un modèle correspond à la valeur de mot, la suite de commandes associée est exécutée, terminant l'exécution de la commande interne composée case.

Les mots case et esac sont des mots-clé ce qui signifie que chacun d'eux doit être le premier mot d'une commande.

suite_de_commandes doit se terminer par deux caractères point-virgule collés, de manière à ce qu'il n'y ait pas d'ambiguïté avec l'enchaînement séquentiel de commandes cmd1 ; cmd2.

Un modèle peut être construit à l'aide des caractères et expressions génériques de bash [cf. § Caractères et expressions génériques]. Dans ce contexte, le symbole | signifie OU.

Pour indiquer le cas par défaut, on utilise le modèle *. Ce modèle doit être placé à la fin de la structure de contrôle case.

Le code de retour de la commande composée case est celui de la dernière commande exécutée de suite_de_commandes.

Exemple 1 : programme shell oui affichant OUI si l'utilisateur a saisi le caractère o ou O

 
Sélectionnez
#!/bin/bash
# @(#) oui
read .p Entrez votre reponse :  rep
case $rep in
o|O ) echo OUI ;;
*) echo Indefini
esac

Rq : il n'est pas obligatoire de terminer par ;; la dernière suite_de_commandes

Exemple 2 : programme shell nombre prenant une chaîne de caractères en argument et qui affiche cette chaîne si elle est constituée d'une suite de chiffres

 
Sélectionnez
#!/bin/bash
# @(#) nombre
shop s case$1in
t-extglob
[:digit:]]) ) echo $1 est une suite de chiffres ;;
+([esac

Exercice : Ecrire un programme shell 4arg qui vérifie que le nombre d'arguments passés lors de l'appel du programme est égal à 4 et écrit suivant le cas le message “Correct” ou le message “Erreur”.

Exercice : Ecrire un programme shell reconnaitre qui demande à l'utilisateur d'entrer un mot, puis suivant le première caractère de ce mot, indique s'il commence par un chiffre, une minuscule, une majuscule ou une autre sorte de caractère.

Exercice : En utilisant la commande unix date et la locale standard [cf. Substitution de commandes], écrire un programme datefr qui affiche la date courante de la manière suivante : mercredi 5 janvier 2005 10:00

VIII-2. Itération while

La commande interne while correspond à l'itération tant que présente dans de nombreux langages de programmation.

Syntaxe :

 
Sélectionnez
while suite_cmd1
do
suite_cmd2
done

La suite de commandes suite_cmd1 est exécutée; si son code de retour est égal à 0, alors la suite de commandes suite_cmd2 est exécutée, puis suite_cmd1 est re-exécutée. Si son code de retour est différent de 0, alors l'itération se termine.

En d'autres termes, suite_cmd2 est exécutée autant de fois que le code de retour de suite_cmd1 est égal à zéro.

L'originalité de cette structure de contrôle est que le test ne porte pas sur une condition booléenne (vraie ou fausse) mais sur le code de retour issu de l'exécution d'une suite de commandes.

En tant que mots-clé, while, do et done doivent être les premiers mots d'une commande.

Une commande while, comme toute commande interne, peut être écrite directement sur la ligne de commande.

Ex :

 
Sélectionnez
$ while who | grep sanchis >/dev/null
> do
> echo lfutilisateur sanchis est encore connecte
> sleep 5
> done
lfutilisateur sanchis est encore connecte
^C
$

Le fonctionnement est le suivant : la suite de commandes who | grep sanchis est exécutée. Son code de retour sera égal à 0 si le mot sanchis est présent dans les résultats engendrés par l'exécution de la commande unix who, c'est à dire si l'utilisateur sanchis est connecté. Dans ce cas, la ou les lignes correspondant à cet utilisateur seront affichées sur la sortie standard de la commande grep. Comme seul le code de retour est intéressant et non le résultat, la sortie standard de grep est redirigée vers le puits (/dev/null). Enfin, le message est affiché et le programme « s'endort » pendant 5 secondes. Ensuite, la suite de commandes who | grep sanchis est ré exécutée. Si l'utilisateur s'est totalement déconnecté, la commande grep ne trouve aucune ligne contenant la chaîne sanchis, son code de retour sera égal à 1 et le programme sortira de l'itération.

Commandes internes while et deux-points

La commande interne deux-points associée à une itération while compose rapidement un serveur (démon) rudimentaire.

 
Sélectionnez
Ex : $ while : => boucle infinie
> do
> who | cut -d' ' -f1 >>fic => traitement à effectuer
> sleep 300 => temporisation
> done &
[1] 12568
$

Lecture du contenu d'un fichier texte

La commande interne while est parfois utilisée pour lire le contenu d'un fichier texte. La lecture s'effectue alors ligne par ligne. Il suffit pour cela :

  • de placer une commande interne read dans suite_cmd1
  • de placer les commandes de traitement de la ligne courante dans suite_cmd2
  • de rediriger l'entrée standard de la commande while avec le fichier à lire.
 
Sélectionnez
Syntaxe : while read [ var1 ... ]
do
commande(s) de traitement de la ligne courante
done < fichier_à_lire

Exemple : programme wh qui affiche les noms des utilisateurs connectés

 
Sélectionnez
#!/bin/bash
# @(#) wh
who > tmp
while read nom reste
do
edone < tmp
cho $nom
rm tmp

Exercice : On dispose d'un fichier personnes dont chaque ligne est constituée du prénom et du genre (m pour masculin, f pour féminin) d'un individu.

 
Sélectionnez
Ex : $ cat personnes
arthur m
pierre m
dominique f
paule f
sylvie f
jean m
$

Ecrire un programme shell tripersonnes qui crée à partir de ce fichier, un fichier garcons contenant uniquement les prénoms des garçons et un fichier filles contenant les prénoms des filles.

 
Sélectionnez
Ex : $ tripersonnes
$
$ cat filles
dominique
paule
sylvie
$
$ cat garcons
arthur
pierre
jean
$

Lorsque le fichier à lire est créé par une commande cmd, comme dans le programme wh, on peut utiliser la syntaxe :

 
Sélectionnez
cmd | while read [ var1 ... ]
do
commande(s) de traitement de la ligne courante
done

Exemple : wh1

 
Sélectionnez
#!/bin/bash
# @(#) wh1
who | while read nom reste
do
echo $nom
done

Par rapport au programme shell wh, il est inutile de gérer le fichier temporaire tmp.

Exercice : En utilisant la commande ruptime écrire un programme shell up qui affiche le nom de toutes les machines qui sont dans l'état up

Exercice :

  1. Ecrire un programme shell etat1 prenant un nom de machine en argument et qui affiche son état (up ou down). On ne considère aucun cas d'erreur.
  2. Modifier ce programme, soit etat2, pour qu'il affiche un message d'erreur lorsque le nom de la machine passé en argument n'est pas visible à l'aide de la commande ruptime.
  3. Modifier le programme précédent, soit etat, pour qu'il vérifie également le nombre d'arguments passés lors del'appel.

Commande interne while et performances

La lecture ligne par ligne d'un fichier à l'aide d'une commande interne while est lente et peu élégante. Il est préférable d'utiliser une suite de filtres permettant d'aboutir au résultat voulu.

Par exemple, en utilisant un filtre supplémentaire (la commande unix cut), on peut s'affranchir de l'itération while dans le programme wh1. Il suffit d'extraire le premier champ de chaque ligne.

La commande unix cut permet de sélectionner un ou plusieurs champs de chaque ligne d'un fichier texte. Un champ peut être spécifié en précisant le caractère séparateur de champ (par défaut, il s'agit du caractère tabulation) avec l'option –d ; les numéros de champs doivent alors être indiqués avec l'option -f.

Programme wh1.cut

 
Sélectionnez
- - - - - - - - - - - - - - - - -
#!/bin/bash
# @(#) wh1.cut
who | cut -d ' ' -f1
- - - - - - - - - - - - - - - - -
 
Sélectionnez
Ex : $ wh1.cut
sanchis
root
$

Dans le programme wh1.cut, on précise que la commande cut doit prendre comme séparateur le caractère espace (-d ' ') et que seul le premier champ de chaque ligne doit être extrait (-f1).

Exercice : Ecrire un programme shell up.cut qui, sans utiliser d'itération, affiche le nom de toutes les machines qui sont dans l'état up.

Une deuxième raison d'éviter la lecture ligne à ligne d'un fichier avec while est qu'elle peut conduire à des résultats différents suivant le mode de lecture choisi (tube ou simple redirection).

Prenons l'exemple où l'on souhaite modifier la valeur d'une variable var après lecture de la première ligne d'un fichier.

Le programme shell maj ci-dessous connecte à l'aide d'un tube la sortie standard de la commande date à l'entrée de la commande interne while. Après lecture de la première (et unique) ligne, la valeur de la variable var est modifiée. Pourtant, cette nouvelle valeur ne sera pas affichée. En effet, l'utilisation du tube a pour effet de faire exécuter l'itération while par un processus différent : il y a alors deux instances différentes de la variable var : celle qui a été initialisée à 0 au début de l'exécution de maj et celle interne au nouveau processus qui initialise à 1 sa propre instance de var. Après terminaison de l'itération while, le processus qui l'exécutait disparaît ainsi que sa variable var initialisée à 1.

Programme maj

 
Sélectionnez
- - - - - - - - - - - - - - - - -
#!/bin/bash
# @(#) maj
var=0
date | while read
do
var=1
done
echo $var
- - - - - - - - - - - - - - - - -
 
Sélectionnez
Ex : $ maj
0
$

Lorsque l'on exécute le programme maj1, bash ne crée pas un nouveau processus pour exécuter l'itération while : il n'y a qu'une instance de la variable var qui est convenablement mise à jour.

Programme maj1

 
Sélectionnez
- - - - - - - - - - - - - - - - -
#!/bin/bash
# @(#) maj1
var=0
date > tmp
while read
do
var=1
done < tmp
rm tmp
echo $var
- - - - - - - - - - - - - - - - -
 
Sélectionnez
Ex : $ maj1
1
$

précédentsommairesuivant

Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.