Note : j'utilise dans cette page les simplifications orthographiques RFF (Règles du Français Facile).
Le but de cette page est de montrer quelques fonctionalités du langage de programation AWK, un langage de traitement de fichiers de texte.
Un programe awk se compose de trois sections dont certaines peuvent être omises :
BEGIN {
/* section d'initiatisation */
}
Règle { /* code à exécuter */ }
END {
/* section finale */
}
Considérons le fichier de donées en entrée data.txt :
abc ; def ; ghi
jkl ; mno;pqr
; stu
vwx ; yz
Voici un premier script AWK composé d'une seule ligne qui ne comporte pas de règle de reconaissance mais juste du code à exécuter. Cela signifie que ce code sera exécuté pour chaque ligne:
/* awk1.awk */
{ print $2 }
L'exécution sera réalisée en utilisant le programme awk et en passant en paramètre le fichier de code awk (option -f) ainsi que le fichier de données :
awk -f awk1.awk data.txt
;
;
stu
;
On pourra également utiliser la syntaxe cat data.txt | awk -f awk1.awk pour exécuter le script.
Le résultat de l'exécution est l'afichage du deuxième mot de chaque ligne car le séparateur par défaut est l'espace. Par exemple pour la première ligne du fichier data.txt, le deuxième mot est le point-virgule.
Si on utilise { print $0; } on affiche l'ensemble de la ligne.
On peut modifier le séparateur de champs FS (Field Separator) qui sépare les mots sur une ligne. Dans notre exemple on va le fixer à ';' dans la section d'initialisation :
BEGIN { FS=";" }
{ print $2 }
Le résultat de l'exécution est alors :
def
mno
stu
yz
AWK possède des variables prédéfinies comme NF (Number of Fields) le nombre de champs (ou de mots) sur une ligne et que l'on peut utiliser dans les scripts
BEGIN { FS=";" }
{ print NF, $2 }
Le résultat de l'exécution est alors :
3 def
3 mno
2 stu
2 yz
NR (Number of Records) est une variable prédéfinie qui correspond à la n-ième ligne du fichier de donées à traiter.
BEGIN { FS=";" }
{ print NR, NF, $2 }
Le résultat de l'exécution est alors :
1 3 def
2 3 mno
3 2 stu
4 2 yz
Il est possible d'utiliser des tableaux (associatifs) afin de stocker des résultats intermédiaires. Voici un petit programe qui stocke le deuxième champs de chaque ligne dans un fichier.
BEGIN {
FS=";"; nbr = 0
}
{
my_array[nbr++] = \$2;
}
END {
print "there are ", nbr, "elements"
for (i in my_array) {
print i, my_array[i]
}
}
Le résultat de l'exécution est alors :
there are 4 elements
0 def
1 mno
2 stu
3 yz
Dans l'exemple qui suit on traite un fichier de donées numériques : on stocke les valeurs dans un tableau et on en calcule la some.
Le fichier de donées en entrée est numeric_data.txt :
# Numeric data
12.5
13.2
8.7
9.78
15.76
Le script à exécuter est :
BEGIN {
FS=";"; nbr = 0
}
/^#/ { print "comment", \$0 }
/^[0-9]+/{
my_array[++nbr] = \$1;
}
END {
print "there are ", nbr, "elements"
sum = 0;
for (i in my_array) {
print i, my_array[i]
sum += my_array[i]
}
print "sum = ", sum
}
Il est composé de deux règles :
Dnas la partie finale on réalise la some des valeurs. On notera la syntaxe particulière for (i in my_array) où i se révèle être un itérateur sur les clés du tableau associatif.
Le résultat de l'exécution est :
there are 5 elements
1 12.5
2 13.2
3 8.7
4 9.78
5 15.76
sum = 59.94
Enfin un dernier exemple (cf stats.awk) qui pour une série de valeurs calcule la some des valeurs, leur moyène, la variance, l'écart type, l'élément minimum et l'élément maximum.
# compute sum, average, var, std dev, min and max
BEGIN {
FS=";";
nbr = 0
}
/^#/ { print "comment", \$0 }
/^[+|-]?[1-9]+[.]?[0-9]*/{
my_array[++nbr] = \$1;
}
END {
print "there are ", nbr, "elements"
sum = 0;
min = max = my_array[1]
for (i in my_array) {
value = my_array[i]
print i, value
sum += value
if (value < min) min = value
if (value > max) max = value
}
avg = sum / nbr
var = 0
for (i in my_array) {
var += (my_array[i] - avg) * (my_array[i] - avg)
}
std = sqrt(var / nbr)
print "---------------"
print nbr, ";", sum, ";", avg, ";", var, ";", std, ";", min, ";", max
}
Sur l'exemple suivant :
# weights
60
56
61
68
51
53
69
54
On obtient :
comment # weights
there are 8 elements
1 60
2 56
3 61
4 68
5 51
6 53
7 69
8 54
---------------
8 ; 472 ; 59 ; 320 ; 6.32456 ; 51 ; 69
Soit :