Vous êtes ici :
Accueil Cours Administration Système La programmation Système avec Shell les structures de contrôle case et while

La programmation Système avec Shell : les structures de contrôle case et while

Choix multiple case

 

 

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 structure while

 

 

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.

 

Commandes internes while et deux-points
 

 

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
$
  

 
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.
 
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.

 

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

 

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
$

 

 




Vous êtes ici :
Accueil Cours Administration Système La programmation Système avec Shell les structures de contrôle case et while