
Syntaxe : 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 :
Soit le programme shell oui affichant OUI si l’utilisateur a saisi le caractère o ou O
#!/bin/bash
read -p "Entrez votre reponse : " rep
case $rep in
o|O ) echo OUI ;;
*) echo Indefini
esac
Remarque : il n’est pas obligatoire de terminer par ;; la dernière suite_de_commandes
Exemple :
le 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
#!/bin/bash
shop s
case $1 in
t - extglob
+([[:digit:]]) ) echo "$1 est une suite de chiffres" ;;
esac
La commande interne while correspond à l’itération tant que présente dans de nombreux langages de programmation.
Syntaxe :
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.
Exemple :
$ while who | grep tony >/dev/null
> do
> echo "l’utilisateur tony est encore connecte"
> sleep 5
> done
l’utilisateur tony est encore connecte
^C
$
Le fonctionnement est le suivant : la suite de commandes who | grep tony est exécutée. Son code de retour sera égal à 0 si le mot tony est présent dans les résultats engendrés par l’exécution de la commande unix who, c’est à dire si l’utilisateur tony 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 tony est réexécutée. Si l’utilisateur s’est totalement déconnecté, la commande grep ne trouve aucune ligne contenant la chaîne tony, son code de retour sera égal à 1 et le programme sortira de l’itération.
La commande interne deux-points associée à une itération while compose rapidement un serveur (démon) rudimentaire.
Exemple :
$ while : => boucle infinie
> do
> who | cut -d' ' -f1 >>fic => traitement à effectuer
> sleep 300 => temporisation
> done &
[1] 12568
$
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.
Syntaxe :
while read [ var1 ... ]
do
commande(s) de traitement de la ligne courante
done < fichier_à_lire
Exemple :
Soit le programme wh qui affiche les noms des utilisateurs connectés
#!/bin/bash
who > tmp
while read nom reste
do
echo $nom
done < tmp
rm tmp
Lorsque le fichier à lire est créé par une commande cmd, comme dans le programme wh précédent, on peut utiliser la syntaxe :
cmd | while read [ var1 ... ]
do
commande(s) de traitement de la ligne courante
done
Exemple :
programme wh1
#!/bin/bash
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.
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.
Exemple :
Soit le programme wh1.cut
#!/bin/bash
who | cut -d ' ' -f1
Exemple d'éxecution :
$ chmod 755 wh1.cut
$ ./wh1.cut
tony
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). 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.
Exemple :
programme maj
#!/bin/bash
var=0
date | while read
do
var=1
done
echo $var
Exemple d'éxecution :
$ chmod 755 maj
$ ./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.
Exemple :
Programme maj1
#!/bin/bash
var=0
date > tmp
while read
do
var=1
done < tmp
rm tmp
echo $var
Exemple d'éxecution :
$ chmod 755 maj1
$ ./maj1
1
$