17.2.1 Etude des fonctionnalit´ ´ es
Le fichier "hosts(5)" permet au syst`eme Unix d’associ´e une adresse r´eseau IP `a un ou plusieurs noms de machine.En se reportant au manuel du fichier "hosts(5)", le format utilis´e est le suivante :
{ Le fichier peut contenir des commentaires, tout caract`ere saisi apr`es le caract`ere "#" est ignor´e,
149
Chapitre 17. Programmation avanc´ee de Shell Scripts
{ Chaque ligne d´ecrivant l’association "adresse IP,noms de machine"
est compos´ee d’au moins deux champs s´epar´es par un ou plusieurs espaces ou tabulations. Le premier champ est l’adresse IP de la machine sous sa forme usuelle (format d´ecimal), le second est le nom officiel de la machine, c’est-`a-dire celui qui lui sera vraiment affect´e. Les autres champs, s´epar´es de la m^eme fa¸con sont les noms non-officiels, c’est-`a-dire une s´erie de noms qu’il sera possible d’utiliser pour la joindre.
Le probl`eme est donc de faire un tri num´erique sur les quatre champs de l’adresse IP (chacun ´etant s´epar´e par le caract`ere "." sachant que le s´eparateur de champ du fichier "hosts" est diff´erent et que les champs le constituant sont diff´erents. De plus, le caract`ere "." peut
^
etre utilis´e dans les noms de machines, en particulier lorsque les domaines Bind/DNS sont pr´ecis´es (cf. [8]).
17.2.2 M´ ethode utilis´ ee
Comme il l’a ´et´e explicit´e pr´ec´edemment, le probl`eme r´eside essentiellement dans les points suivants :
{ le s´eparateur de champ pour le fichier "hosts(5)" est diff´erent de celui qui pourrait nous servir pour faire le tri sur les champs de l’adresse IP,
{ le nom d’une machine, si son domaine est sp´ecifi´e, peut comporter un certain nombre de ".", lui-m^eme s´eparateur de champs pour l’adresse IP (cf [8]),
{ le tri doit ^etre effectu´e en num´erique uniquement sur les champs de l’adresse IP.
Il est clair, que la commande `a utiliser pour faire ce tri, est la commande "sort(1)". Par contre, nous devrons faire en sorte que l’entr´ee du tri comporte cinq champs :
{ le premier champ num´erique de l’adresse IP, { le second champ num´erique de l’adresse IP, { le troisi`eme champ num´erique de l’adresse IP, { le quatri`eme champ num´erique de l’adresse IP, { le ou les noms de la machine.
Il suffira alors de faire un tri num´erique sur les quatre premiers champs. Le r´esultat `a afficher devra reformatter de telle sorte qu’il ob´eisse au format du fichier "hosts(5)".
Nous aurons donc les ´etapes suivantes :
1. convertir le fichier "hosts(5)" de telle sorte que l’on dispose des cinq champs explicit´es pr´ec´edemment,
2. effectuer le tri,
3. reformatter le r´esultat du tri pour ob´eir au format usuel et l’afficher sur la sortie standard.
Or, un nom de machine peut utiliser le caract`ere "." afin d’identifier son domaine DNS. Par cons´equent, il faudra utiliser un autre caract`ere pour s´eparer
17.2. Tri par adresse IP du fichier ”/etc/hosts”
17.2.3 D´ eveloppement
Comme tout script Unix, le but est de n’utiliser, dans la mesure du possible, aucun fichier temporaire. Comme il l’a ´et´e d´evelopp´e au paragraphe pr´ec´edent, il est clair que les r´esultats s’enchainent les uns aux autres. Nous utiliserons donc les m´ecanismes de redirection d’entr´ee/sortie et des filtres.
Apr`es les commentaires d’ent^ete d’usage, la premi`ere chose `a faire est de reformatter le fichier "hosts(5)" pour l’envoyer `a la commande de tri "sort(1)". Pour cela, nous utiliserons la commande "sed(1)".
Celle-ci nous servira, dans un premier temps, `a supprimer les ´eventuels commentaires du fichier (pour plus de d´etails, cf. 15.4.3). Nous aurons donc :
sed -e ’/^#.*/d’ -e ’s/#.*$//’ /etc/hosts
Dans un deuxi`eme temps, la commande "sed(1)" va nous servir `a reformatter l’adresse IP, afin de substituer le caract`ere "." par le caract`ere
" :". Sachant que le format d’une telle adresse est compos´e de quatre nombres s´epar´es par ".", l’expression r´eguli`ere suivante la d´ecrit parfaitement :
[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*
Par cons´equent, toute ligne du fichier "host(5)" peut ^etre d´ecrite par l’expression suivante :
\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\(.*$\)
Ce qui nous permet d’avoir les r´ef´erences suivantes pour l’expression r´eguli`ere :
R´ef´erence Description
\1 Premier champ num´erique de l’adresse IP.
\2 Second champ num´erique de l’adresse IP.
\3 Troisi`eme champ num´erique de l’adresse IP.
\4 Quatri`eme champ num´erique de l’adresse IP.
\5 Noms de la machine.
Nous pourrons donc ´ecrire la requ^ete de substitution suivante :
s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\(.*$\)/\1:\2:\3:\4:\5/
Ce qui nous donne :
sed -e ’/^#.*/d’ -e ’s/#.*$//’ /etc/hosts |\
sed -e \
’s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\(.*$\)/\1:\2:\3:\4:\5/’
Il ne reste plus qu’`a effectuer le tri sachant que :
{ le tri doit s’effectuer par ordre num´erique croissant sur les quatre premiers champs,
{ chaque champ est s´epar´e par le caract`ere " :".
Nous obtenons :
S.Baudry, Introduction `a la programmation Bourne Shell – v4.0 151
Chapitre 17. Programmation avanc´ee de Shell Scripts
sed -e ’/^#.*/d’ -e ’s/#.*$//’ /etc/hosts |\
sed -e \
’s/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\(.*$\)/\1:\2:\3:\4:\5/’ |\
sort -t: +n
Il faut maintenant reformatter le r´esultat pour obtenir celui qui est conforme au fichier "hosts(5)". Nous allons ici utiliser lLa commande
"awk(1)". Celle-ci recevra donc des lignes (ou enregistrements) s´epar´es par le caract`ere " :" et devra effectuer le traitement suivant pour chacunes :
{ afficher le premier champ, { afficher le caract`ere ".", { afficher le second champ, { afficher le caract`ere ".", { afficher le troisi`eme champ, { afficher le caract`ere ".", { afficher le quatri`eme champ, { afficher le cinqui`eme ,
{ ins´erer un retour `a la ligne pour marquer la fin de l’enregistrement obtenu en r´esultat.
Nous avons donc : awk ’
BEGIN { FS=":" } {
printf ("%d.%d.%d.%d%s\n", ^$1, $2, $3, $4, $5) }
’
17.2.4 Programme obtenu
#!/bin/sh
#
# Description : Tri du fichier /etc/hosts par adresse IP
#
# Appel du programme : sorthost
#
# Fichiers externes : Non
#
printf ("%d.%d.%d.%d%s\n", ^$1, $2, $3, $4, $5) }
’