Blog ENI : Toute la veille numérique !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
💥 Les 22 & 23 novembre : Accès 100% GRATUIT
à la Bibliothèque Numérique ENI. Je m'inscris !
  1. Livres et vidéos
  2. Expressions régulières
  3. Quelques exercices récapitulatifs
Extrait - Expressions régulières Syntaxe et mise en œuvre (avec exercices et corrigés) (2e édition)
Extraits du livre
Expressions régulières Syntaxe et mise en œuvre (avec exercices et corrigés) (2e édition) Revenir à la page d'achat du livre

Quelques exercices récapitulatifs

Introduction 

Cette section propose quelques exercices utilisant des éléments vus dans les chapitres précédents, et permet une mise en application simple et concrète des syntaxes, principes et conseils présentés dans cet ouvrage.

shell, sed, awk 

Détermination du jour de la semaine d’une date donnée 

Utiliser la commande cal (qui génère un calendrier), ainsi que les commandes sed et awk pour écrire un shell script qui donne le jour de la semaine d’une date donnée.

Indications

La commande cal (disponible sous UNIX et Linux) peut afficher un extrait de calendrier pour un mois et une année spécifiés, comme par exemple :

cal 05 2015 

qui affiche le résultat suivant :

      May 2015         
Su Mo Tu We Th Fr Sa   
               1  2   
3  4  5  6  7  8  9   
10 11 12 13 14 15 16   
17 18 19 20 21 22 23   
24 25 26 27 28 29 30   
31                     

Il suffit donc d’écrire un shell script prenant en argument les informations relatives au jour que l’on recherche, et de localiser sa position dans le calendrier du mois pour déterminer le jour de la semaine.

On pourra prendre comme syntaxe d’appel du script la syntaxe suivante :

dow JJ MM AAAA 

dow est le nom du script (Day Of Week, ou jour de la semaine), JJ est le numéro du jour dans le mois, MM est le numéro du mois dans l’année, et AAAA est l’année.

Solution

#!/bin/bash  
EXP1='s/\(..\) /\1:/g'  
EXP2='1,2d;s/ //g'  
 
if [ "$3" = "" -o "$4" != "" ]  
then  
    echo "Usage: `basename $0` JJ MM AAAA"  
    exit 1  
fi  
 
cal $2 $3 | sed "$EXP1" | awk -F: '{  
    for (i = 1; i <= 7; i++) {  
         if (i <= NF) {  
              printf("%s", $(i));  
         }  
         if (i < 7) {  
              printf(":");  
         }  
    }  
    printf("\n");  
}' | sed "$EXP2" | awk -F: 'BEGIN {  
    days = "Dimanche:Lundi:Mardi:Mercredi:Jeudi:Vendredi:Samedi" 
}  
{  
    for (i = 0; i <= 7; i++) {  
         t[$(i)] = i;  
    }  
}  
END {  
    $0 = days;  
    if ("'$1'" in t) {  
         print $(t["'$1'"]);  
    }  
    else {  
         printf("%s-%s-%s n'"'"'existe pas\n", "'$1'", "'$2'", "'$3'"); 
    }  
}' 

Le code :

if [ "$3" = "" -o "$4" != "" ] 
then  
    echo "Usage: `basename $0` JJ MM AAAA" 
    exit 1 
fi 

contrôle que le script dow est bien appelé avec trois arguments : il affiche un message indiquant l’usage du script si le troisième argument est vide ("$3" = "") ou si le quatrième n’est pas vide ("$4" != "").

Notez bien les doubles quotes indispensables autour des noms de variables positionnelles $3 et $4. Si elles étaient absentes, l’appel du script avec moins de trois arguments provoquerait une erreur de syntaxe car la variable $3 serait supprimée, et non remplacée par une chaîne vide.

Le code :

cal $2 $3 | sed "$EXP1" 

est après substitution identique au code :

cal $2 $3 | sed 's/\(..\) /\1:/g' 

qui a pour but de remplacer chaque espace situé après deux caractères quelconques par le caractère :.

Par exemple, la commande :

cal 05 2015 

qui affiche :

      May 2015         ...

find, egrep, hl 

Colorisation d’un répertoire de niveau donné 

Rechercher sous le répertoire /usr tous les fichiers réguliers dont le nom ne se termine pas par .dict ni par .sty, ayant au moins 11 niveaux de répertoires, coloriser en bleu les neuf premiers niveaux, en cyan le dixième niveau, en magenta les éventuels niveaux de répertoires supplémentaires, et en rouge le nom court des fichiers.

Solution

find /usr ! -name '*.dict' ! -name '*.sty' -type f -print \  
    2> /dev/null | \  
egrep '^(/[^/]+){10}/' | \  
hl -e -b "^(/[^/]+){8}/" -c "^(/[^/]+){9}/" -r '[^/]+$' -m '.+' 

La commande find recherche sous le répertoire /usr tous les fichiers (au sens large) dont le nom ne se termine pas par .dict (! -name ’*.dict’), ni par .sty (! -name ’*.sty’), dont le type est fichier régulier (-type f), et les affiche (-print). 

La redirection 2> /dev/null permet d’éviter de polluer le résultat au cas où certains répertoires ne seraient pas lisibles par l’utilisateur lançant la commande.

La sélection des noms longs comportant au moins 11 niveaux de répertoires est effectuée par la commande egrep de la façon suivante :

egrep sélectionne les lignes fournies par find en n’affichant que celles qui comportent en début de ligne...