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