Cette commande permet d'appliquer un certain nombre d'actions sur un fichier. La syntaxe est inspirée du C. L'utilitaire awk emprunte son nom à l'identité de ses trois auteurs (Aho, Weinberger et Kernighan). Il s'agit d'un véritable langage permettant l'écriture de filtres. En effet, il permet d'extraire parmi les lignes d'un fichier des informations sélectionnées et offre la possibilité de réaliser des comparaisons et des calculs sur des champs et de réorganiser les lignes. Il permet l'écriture rapide de tels filtres pour exploiter les résulats de programmes et ne nécessite aucune compilation.
Généralités
La syntaxe de la commande est la suivante:
awk [-F] car [-fref_prog] [ref...]
L'option -F: par défaut, le séparateur lorsque vous tapez une commande UNIX est l'espace. Ainsi, si vous tapez echo bonjour, le séparateur entre ``echo'' et ``bonjour'' est bien l'espace. Si on revient à awk, il faut bien comprendre que cette commande va effectuer des recherches dans les fichiers, en utilisant par exemple l'espace comme séparateur. Cependant, dans certains fichiers comme celui des mots de passe, les seuls séparateurs que l'on trouve sont formés de ``:''. On utilisera alors l'option -F ":" pour analyser le fichier de mots de passe suivant :
l'option -f et [ref...]: les filtres que l'on applique à un fichier sont parfois relativement longs à taper comme ça en ligne. Dès lors il est plus simple de taper le filtre dans un fichier que l'on passera en argument à la commande awk. Ainsi, awk -f prog.awk demo.txt va appliquer le filtre contenu dans prog.awk au fichier demo.txt (qui joue ici le rôle du paramètre [ref...]).
Un premier exemple
Un fichier soumis à un programme awk est découpé en enregistrements logiques (par défaut des lignes) eux mêmes découpés en champs. Un enregistrement (respectivement un champ) est une suite de caractères consécutifs délimitée par un caractère distingué (un délimiteur) qui, par défaut est le caractère de fin de ligne (respectivement un caractère d'espacement <SPACE>) De façon générale, $1, $2, ... désignent le premier champ, le second champ, ... de l'enregistrement courant et $0 cet enregistrement en totalité.
Voyons un petit exemple: créez le fichier eleves.txt suivant:
BOBY 18 5
ZELYNOU 6 11
ANTIN 8 4
BOB 16 8 15
IZEL 16 18 12
Enfin, lancez la commande suivante et voyez le résultat :
awk -f awk.prg eleves.txt
Explication: le traitement de chaque ligne se fait par une commande écrite entre accolades { et } . A présent, modifiez le fichier awk.prg comme suit et testez à nouveau par awk -f awk.prg eleves.txt (les commentaires sont précédés d'un #).
Awk met à la disposition du programmeur des variables:
nom de la variable
résultat
NF
nombre de champs de l'enregistrement courant
NR
numéro de l'enregistrement en cours de traitement,
en particulier NR aura comme valeur tout à la fin
le nombre total d'enregistrements
FILENAME
nom du fichier ouvert
Awk met à la disposition du programmeur un nombre considérable de fonctions dont voici un extrait des plus utiles :
nom de la fonction
résultat
length(s)
retourne la longueur de la chaine s
index(s1,s2)
donne la position de la première occurence de s2 dans s1.
La valeur est 0 si il n'y a aucune occurence
gsub(r,s,t)
sur la chaine t, remplace toutes les occurences de r par s
sub(r,s,t)
comme gsub, mais remplace uniquement la première occurence
substr(s,i,n)
retourne la sous chaine de s commençant en i et de taille n
Exercice: écrire un fichier awk.prg qui permettra d'obtenir le résultat suivant à partir du fichier eleves.txt (le rôle de ce filtre est de remplacer toute lettre ``Z'' par la lettre ``a'' :
BOBY 18 5
aELYNOU 6 11
ANTIN 8 4
BOB 16 8 15
IaEL 16 18 12
Awk dispose enfin d'instructions:
Conditionnelles
if (expr)
instruction else instruction
Itérations
while (expr)
instruction
ou
for (expr,expr,expr)
instruction
ou
for (varintableau)
instruction
On dispose également de:
=: affectation
++: incrémentation de 1
+=: incrémentation variable
exemple :
while( i*i < n ) { i++ }
for (i=a;i<=b;i+=2) {
if (i*i==n) { print "trouvé" }
else
{ print i n i*i }
} # finpour i
Awk initialise automatiquement les variables. Ainsi i est automatiquement initialisé à 0 au départ.
A présent, il ne nous reste plus qu'à revoir les expressions régulières ainsi que la syntaxe générale d'un fichier awk et nous pourrons dès lors écrire pratiquement n'importe quelle commande du type awk.
Rappels: les expressions régulières
Une expression régulière est une chaîne de caractère définie par des caractères, des répétititions de caractères ou des positions de caractères. Après les caractères, on peut mettre
*: pour indiquer la répétition 0 fois ou plus
+: pour indiquer la répétition 1 fois ou plus
?: pour indiquer la répétition 0 fois ou 1 fois
Ainsi A*B correspond à B ou AB ou AAB ou AAAB etc.
On dispose aussi des symboles :
[ : indicateur du début de la définition d'un ensemble de caractères
] : indicateur de la fin de la définition d'un ensemble de caractères
. : désigne un caractère quelconque excepté le caractère de fin de ligne
^ : pour indiquer le début de chaîne (si se situe derrière un [, il signifie complément de l'ensemble correspondant
$: pour indiquer la fin de ligne
Voici quelques expressions régulières et leur signification:
^B: chaîne qui commence par B
B$: chaîne qui finit par B
^.$: chaîne qui a un seul caractère
[AEIOU]: chaîne avec une seule voyelle majuscule
^[ABC]: chaîne qui commence par A ou B ou C
^[^a-z]$:chaîne à un seul caractère qui n'est pas une minuscule
Exercice : écrire les expressions régulières suivantes.
ensemble de tous les caractères alphanumériques
ensemble complémentaire du précédent
lignes qui ne contiennent que des lettres minuscules, c.à.d du premier au dernier caractère
chaîne non nulle avec seulement des chiffres.
Voir la page des solutions
La forme générale des programmes transmis à awk
Pour simplifier, un programme ou un filtre awk est divisé en trois sections, (don't panic, un exemple suivra):
La section initiale
BEGIN {actions}
Les actions de cette section seront exécutées avant l'examen de la première ligne du fichier à examiner.
Le corps est constitué d'une suite de couples de la forme
{ actions }
ou
/ motif / { actions }
Dans le premier cas: { actions }, on traite toutes les lignes. C'est ce que l'on faisait jusqu'à présent. Dans le second cas: motif { actions }, awk va lire le fichier texte ligne par ligne à la recherche de certains motifs particuliers (dans notre cas, des expressions régulières). Dès qu'il aura trouvé un certain motif (matching d'un motif), il fera une action.
La section finale
END {actions}
Les actions de cette section seront exécutées après l'examen de la dernière ligne du fichier à examiner.
Essayez les deux exemples suivants sur le fichier eleves.txt :
Exemple 1 qui n'utilise pas de motifs:
END {
printf ("Votre fichier contient %d lignes",NR)
{}
Exemple 2:
BEGIN {
printf ("Affichage des lignes du fichier %s contenant du texte en majuscules
antislash_n",FILENAME)
}
Exercices
Recherche d'une chaîne de caractères
Ecrire un filtre awk1.prg qui affiche toutes les lignes du fichier eleves.txt qui contiennent la chaîne BO
Voir la page des solutions
Numérotation des lignes d'un fichier
Ecrire un filtre awk2.prg qui numérote toutes les lignes du fichier eleves.txt. Le résultat de l'exécution sera de la forme:
1 BOBY 18 5
2 ZELYNOU 6 11
3 ANTIN 8 4
4 BOB 16 8 15
5 IZEL 16 18 12
Voir la page des solutions
Recherche d'une chaîne de caractères particulière
Ecrire un filtre awk3.prg qui affiche toutes les lignes du fichier eleves.txt qui contiennent une lettre ``E'' suivie d'un nombre quelconque de lettres puis impérativement le chiffre 1
Voir la page des solutions
Pour clore sur awk
Motifs
L'expression / motif / { actions } n'est pas la seule possible pour engendrer une action. On peut faire des choses du type:
Les deux premiers types d'expression relationnelles indiquent respectivement que l'expression gauche (ici: expression) doit ou ne doit pas contenir de motif satisfaisant l'expression régulière droite. Par exemple, l'expression $2 / a[0-9]*b$/ spécifie que le second champ de l'enregistrement courant doit commencer par le caractère a, se terminer par le caractère b, les caractères intermédiaires devant être des chiffres (en nombre quelconque, éventuellement nul).
De la puissance de awk
Si les exemples que nous avons vus sont relativement succincts, il faut bien comprendre que awk est en fait une commande très puissante qui est d'ailleurs très utilisée par l'un de nos administrateurs système dans la maison (parlez-lui de Linux ou de awk, ça lui fera plaisir ;-) )
Voici un exemple succint pour contrôler que tous les enregistrements d'un fichier ont le même nombre de champs que le premier enregistrement. Faites un copier coller du programme qui suit et testez le par:
awk -f awk.prg -F ":" /etc/passwd
# début de la section initiale
BEGIN {
printf("Contrôle du fichier%s antislash_n",FILENAME);
nberr=0;
}
# début du corps
{
if (NR == 1) {
nb=NF;
printf("Chaque enregistrement doit comporter %d champs antislash_n",nb); }
else if (nb != NF) {
printf("L'enregistrement %d a %d champs antislash_n",NR,NF);
nberr++;}
}
# début de la section terminale
END {
printf("Le fichier a %d enregistrements antislash_n",NR);
if (nberr!=0)
printf("Tous les enregistrements sont corrects antislash_n");
}
Conclusion
Au terme de ce bureau d'étude, vous êtes donc opérationnel sous UNIX. Si vous êtes amenés dans la suite de votre cursus à manipuler des commandes inconnues vous pouvez toujours faire un man nom_commande ou encore consulter la bible de la programmation UNIX :
La programmation sous UNIX Jean-Marie RIFFLET EDISCIENCE International
Septembre 1998