S'abonner à Techno Geek

Linux‎ > ‎

AWK

Introduction


Awk est un langage de traitement de lignes, disponible sur la plupart des systèmes Unix. Sont utilisation est principalement destinée au parsing de fichier plat.

Exemple d'utilisation

L'exemple suivant concerne un fichier de log d'acces à un serveur Web.


Format du fichier access.log en entrée:

cyber06 - - [18/Feb/2011:10:17:37 +0100] "GET /web/guest/3 HTTP/1.1" 504 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 134
cyber06 - - [18/Feb/2011:10:18:43 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 18
cyber06 - - [18/Feb/2011:10:18:48 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 34
cyber06 - - [18/Feb/2011:10:18:52 +0100] "GET /web/cyber06/page.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 22
cyber06 - - [18/Feb/2011:10:19:13 +0100] "GET /web/cyber06/stat.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 20
cyber06 - - [18/Feb/2011:10:19:49 +0100] "POST /web/cyber06/test.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 56
cyber06 - - [18/Feb/2011:10:20:15 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 111
cyber06 - - [18/Feb/2011:10:21:35 +0100] "GET /web/cyber06/page.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 13
cyber06 - - [18/Feb/2011:10:21:36 +0100] "GET /web/cyber06/test2.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 34
cyber06 - - [18/Feb/2011:10:22:53 +0100] "POST/web/cyber06/page3.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 46
cyber06 - - [18/Feb/2011:10:23:44 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 45 20



Exemple 1: Affichage des requêtes avec un code retour HTTP 200


awk '$9~/200/ {print $0}' access.log
cyber06 - - [18/Feb/2011:10:18:43 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 18
cyber06 - - [18/Feb/2011:10:18:48 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 34
cyber06 - - [18/Feb/2011:10:18:52 +0100] "GET /web/cyber06/page.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 22
cyber06 - - [18/Feb/2011:10:19:13 +0100] "GET /web/cyber06/stat.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 20
cyber06 - - [18/Feb/2011:10:19:49 +0100] "POST /web/cyber06/test.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 56
cyber06 - - [18/Feb/2011:10:20:15 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 111
cyber06 - - [18/Feb/2011:10:21:35 +0100] "GET /web/cyber06/page.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 13
cyber06 - - [18/Feb/2011:10:21:36 +0100] "GET /web/cyber06/test2.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 34
cyber06 - - [18/Feb/2011:10:22:53 +0100] "POST /web/cyber06/page3.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 46
cyber06 - - [18/Feb/2011:10:23:44 +0100] "GET /web/cyber06/index.html HTTP/1.1" 200 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 20


La commande ci dessus se décompose de la façon suivante

awk 'motif {action}'  fichier


Pour chaque ligne du fichier si le motif correspond l'action sera exécutée.

le motif est une expression régulière qui ici vaut :

$9~/200/


$9 correspond à la position du champs dans la ligne nous vérifions donc ici que le 9éme champs vaut 200

une variante pourrait être :

awk '$9!~/200/ {print $0}' access.log


Le motif cette fois indique que l'action ne se fera que lorsque le 9éme champs est différent de 200

awk '$9!~/200/ {print $0}' access.log
cyber06 - - [18/Feb/2011:10:17:37 +0100] "GET /web/guest/3 HTTP/1.1" 504 239 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13" 134


L'action consiste ici à afficher $0 c'est à dire la ligne complète

Exemple 2: Nombre de requêtes avec un code retour HTTP 200

awk '$9~/200/ {counter++} END{print counter}' access.log
10



La commande ci dessus se décompose de la façon suivante

awk 'motif {action} END{actionFinale}'  fichier


Cette fois ci la cinématique est la suivante pour chaque ligne du fichier nous vérifions le motif, lorsque celui ci est validé l'action est réalisée, une fois la fin du fichier atteinte l'actionFinale est réalisée

l'action correspond à l'incrémentation de la variable counter
et actionFinale à l'affichage de cette variable counter

Exemple 3: Temps de réponse des requêtes avec un code retour HTTP 200

 awk '$9~/200/ {counter++; tps+=$NF} END{print tps/counter}' access.log
37,4


La commande ci dessus se décompose de la façon suivante

awk 'motif {action} END{actionFinale}'  fichier


l'action comporte 2 instructions; l'incrémentation du nombre de requêtes en 200 ainsi que l'incrémentation d'un compteur de temps de réponse totale de requête en 200
l'actionFinale affiche la division du temps total par le nombre totale de requête en 200.

Un bloc BEGIN peut être rajouté de la même manière que END les actionBegin sera exécutée uniquement avant traitement de la première ligne.

awk 'BEGIN{print "Début de traitement"} {print "traitement de la ligne " NR} END{print "fin de traitement"}' access.log

awk 'BEGIN{print "Début de traitement"} {print "traitement de la ligne " NR} END{print "fin de traitement"}' access.log
Début de traitement
traitement de la ligne 1
traitement de la ligne 2
traitement de la ligne 3
traitement de la ligne 4
traitement de la ligne 5
traitement de la ligne 6
traitement de la ligne 7
traitement de la ligne 8
traitement de la ligne 9
traitement de la ligne 10
traitement de la ligne 11
fin de traitement


NF correspond à la position du dernier champs de la ligne ici le 22éme champs, $NF correspond a la valeur du dernier champs de la ligne ($NF équivaut donc à $22)

awk '$9~/200/ {print "le dernier champs est le champs: " NF " et vaut "$NF}' access.log
le dernier champs est le champs: 22 et vaut 18
le dernier champs est le champs: 22 et vaut 34
le dernier champs est le champs: 22 et vaut 22
le dernier champs est le champs: 22 et vaut 20
le dernier champs est le champs: 22 et vaut 56
le dernier champs est le champs: 22 et vaut 111
le dernier champs est le champs: 22 et vaut 13
le dernier champs est le champs: 22 et vaut 34
le dernier champs est le champs: 22 et vaut 46
le dernier champs est le champs: 23 et vaut 20


Le numéro de la ligne est donné par NR

awk '$9~/200/ {print "le dernier champs de la ligne "  NR " est le champs: " NF " et vaut "$NF}' access.log
le dernier champs de la ligne 2 est le champs: 22 et vaut 18
le dernier champs de la ligne 3 est le champs: 22 et vaut 34
le dernier champs de la ligne 4 est le champs: 22 et vaut 22
le dernier champs de la ligne 5 est le champs: 22 et vaut 20
le dernier champs de la ligne 6 est le champs: 22 et vaut 56
le dernier champs de la ligne 7 est le champs: 22 et vaut 111
le dernier champs de la ligne 8 est le champs: 22 et vaut 13
le dernier champs de la ligne 9 est le champs: 22 et vaut 34
le dernier champs de la ligne 10 est le champs: 22 et vaut 46
le dernier champs de la ligne 11 est le champs: 23 et vaut 20


PS la ligne 1 n'est pas affichée car le code retour HTTP (champs $9 ne vaut pas 200) pour afficher toute les lignes le motif doit être supprimé:

awk '{print "le dernier champs de la ligne "  NR " est le champs: " NF " et vaut "$NF}' access.log
le dernier champs de la ligne 1 est le champs: 22 et vaut 134
le dernier champs de la ligne 2 est le champs: 22 et vaut 18
le dernier champs de la ligne 3 est le champs: 22 et vaut 34
le dernier champs de la ligne 4 est le champs: 22 et vaut 22
le dernier champs de la ligne 5 est le champs: 22 et vaut 20
le dernier champs de la ligne 6 est le champs: 22 et vaut 56
le dernier champs de la ligne 7 est le champs: 22 et vaut 111
le dernier champs de la ligne 8 est le champs: 22 et vaut 13
le dernier champs de la ligne 9 est le champs: 22 et vaut 34
le dernier champs de la ligne 10 est le champs: 22 et vaut 46
le dernier champs de la ligne 11 est le champs: 23 et vaut 20


Exemple 4: Temps de réponse des requêtes avec un code retour HTTP 200 par type de requête


awk '$9~/200/ {counter[$7]++; tps[$7]+=$NF} END{for(requete in tps){ print  counter[requete] " requetes: " requete " tps de reponse moyen de la requete " tps[requete]/counter[requete] "ms"}}' access.log
1 requetes: /web/cyber06/page3.html tps de reponse moyen de la requete 46ms
1 requetes: /web/cyber06/test2.html tps de reponse moyen de la requete 34ms
1 requetes: /web/cyber06/test.html tps de reponse moyen de la requete 56ms
1 requetes: /web/cyber06/stat.html tps de reponse moyen de la requete 20ms
4 requetes: /web/cyber06/index.html tps de reponse moyen de la requete 45,75ms
2 requetes: /web/cyber06/page.html tps de reponse moyen de la requete 17,5ms


counter[$7]
est une table de hash avec comme clef $7 (valeur du champs correspondant à la requête) qui est incrémentée à chaque fois que le motif est réalisé.
tps[$7]
est une table de hash avec comme clef $7 qui est incrémenté de la valeur du temps de réponse (dernier champs)  à chaque fois que le motif est réalisé.

Il est possible de formater le code pour plus de lisibilité:

awk '$9~/200/ {
    counter[$7]++;
    tps[$7]+=$NF
    }
    END{
        for(requete in tps){
            print  counter[requete] " requetes: " requete " tps de reponse moyen de la requete " tps[requete]/counter[requete] "ms"
        }
    }' access.log





Comments