Skip to content

AWK⚓︎


Généralités⚓︎

Awk est un outil pour la manipulation de fichiers (au format texte).
Il a été conçu en 1977 par Alfred **A**ho, Peter **W**einberger et Brian **K**ernighan (Laboratoires Bell) et intégré dans Unix V7 en 1979.

Awk est aujourd'hui dans la norme POSIX (donc intégré dans toutes les distributions Unix, Linux, etc.)

Cette commande permet d'appliquer un certain nombre d'actions sur un fichier.
Elle est particulièrement adaptée au fichiers qui sont sous forme de lignes/colonnes, comme le CSV par exemple.

La syntaxe est inspirée du C.


Syntaxe⚓︎

awk [-Fs] [-v variable] [-f fichier de commandes] '**programme awk**' fichier 
-F : Spécifie les séparateurs de champs 
-v : Définie une variable utilisée à l'intérieur du programme. 
-f : les commandes sont lu à partir d'un fichier. 

Fonctionnement⚓︎

Le programme awk est une suite d'action de la forme :

motif { action }

Vacobulaire

Un enregistrement est : une chaîne de caractères séparée par un retour chariot, en général une ligne.
Un champs est : une chaîne de caractères séparée par un espace (ou par le caractère spécifié par l'option -F), en général un mot.
Le motif : condition qui permet de déterminer sur quels enregistrements est appliquée l'action.

Variables prédéfinies⚓︎

Liste non exhaustive ...

Variable Signification Valeur par défaut
ARGC Nombre d'arguments de la ligne de commande -
ARGV Tableau des arguments de la ligne de commande -
FNR Nombre d'enregistrements du fichier -
NF Nombre de champs dans l'enregistrement courant -
NR Nombre d'enregistrement déjà lus -
FS Séparateur de champs d'entrée " "
RS Séparateur d'enregistrement en entrée "\n"
OFS Séparateur de champs de sortie " "
ORS Séparateur d'enregistrement de sortie "\n"
... ... ...

Le motif⚓︎

Si le motif existe dans l'enregistrement, l'action sera appliquée à la ligne.
Le motif peut être :

  • une expression régulière :
    • /expression regulière/
    • $0 ~ /expression regulière/
    • expression ~ /expression regulière/
    • expression !~ /expression regulière/
  • une expression BEGIN ou END
  • une expression de comparaison: <, <=, == , !=, >=, >
  • une combinaison des trois (à l'aide des opérateurs booléens || ou, && et, ! négation)

On accède à chaque champs de l'enregistrement courant par la variable $1, $2, ... $NF.

$0 correspond à l'enregistrement complet.
La variable NF contient le nombre de champs de l'enregistrement courant, la variable $NF correspond donc au dernier champs.

L'action⚓︎

Une action transforme ou manipule des données, par défaut on print la ligne.

Type des actions :
- fonctions prédéfinies, numérique ou chaîne de caractères
- contrôle de flots
- affectation
- impression

Actions possibles :

  • Les opérations arithmétiques usuelles : + - * / % (reste division entière) et ^ (puissance).
    Tous les calculs sont effectués en virgule flottante.
    Vous pouvez aussi utiliser les opérateurs +=, -=, *=, /=, %= etc ...

  • Les affectations : var = expression

  • Références aux variables de champs :
    Les champs de la ligne courant sont : $1, $2, ..., $NF. La ligne entière est $0.
    Ces variables ont les mêmes propriétés que Les autres variables.
    Elles peuvent être réaffectées. Quand $0 est modifiées, les variables $1, $2 ... sont aussi modifiées ainsi que NF.
    Inversement si une des variables $i est modifiées, $0 est mise à jour.
    Les champs peuvent être spécifiés par des expressions, comme $(NF-1) pour l'avant dernier champs.

  • Impression :
    print $i par exemple ...

  • If/Else, Boucles

    if (condition) 
    { ... }
    else
    { ... }
    
    while (condition) 
    { ... }
    
    for (init ;cond ;incr)
    { ... }
    

  • Commentaire : #

  • next: passe à l'enregistrement suivant. On reprend le script awk à son début.

  • exit: ignore le reste de l'entrée et execute les actions définie par END

Liste non exhaustive de fonction sur chaines de charactères :
Dans le tableau suivant s et t représentent des chaînes de caractères, r une expression régulière, i et n des entiers.

Fonction Signification
length(s) Retourne la longueur de la chaine s
gsub(r,s,t) Dans la chaine t, remplace toutes les occurences de r par s
substr(s,i,n) Retroune la sous chaîne de s commençant en i et de taille n
... ...

Concaténation de chaînes de caractères dans les actions :
Il n'y a pas d'opérateur de concaténation, il faut simplement lister les chaînes à concaténer.

Exemples :
awk '{ print NR " : " $0 }' fichier


Exemples⚓︎

Script Resultat
awk -F ":" '{ $2 = "" ; print $0 }' /etc/passwd Imprime chaqe ligne du fichier /etc/passwd après avoir effacé le 2nd champ
awk ' END { print NR }' fichier Imprime le nombre total de lignes du fichier
awk '{ print $NF }' fichier Imprime le dernier champ de chaque ligne
who | awk '{ print $1,$5 }' Imprime le login et le temps de connexion
awk ' length($0) > 75 { print }' fichier Imprime les lignes de plus de 75 caractères ( print équivaut à print $0

Exercices⚓︎

awk 'BEGIN { print "Verification des UID et GID dans le fichier /etc/passwd"; FS=":"}      
     $3 !~ /^[0-9][0-9]*$/ {print "UID  erreur ligne "NR" :\n"$0 }
     $4 !~ /^[0-9][0-9]*$/ {print "GID  erreur ligne "NR" :\n"$0 }
     END   { print "Fin" }' /etc/passwd 
Solution
Vérification des UID et GID dans le fichier /etc/passwd
UID erreur ligne 14 : 
clown:*:aaa:b:utilisateur en erreur:/home/clown:/bin:sh
GID erreur ligne 14 : 
clown:*:aaa:b:utilisateur en erreur:/home/clown:/bin/sh
Fin 
awk 'BEGIN { print "Verification du fichier /etc/passwd pour ..."; print "- les utilisateurs avec UID = 0 " ;  print "- les utilisateurs avec UID >= 60000" ; FS=":"}
     $3 == 0 { print "UID 0 ligne "NR" :\n"$0 }      
     $3 >= 60000  { print "UID >= 60000 ligne "NR" :\n"$0 }      
     END   { print "Fin" }' /etc/passwd       
Solution
Verification du fichier /etc/passwd pour ...
- les utilisateurs avec UID = 0 
- les utilisateurs avec UID >= 60000UID 0 ligne 5 : 
root:*:0:b:administrateur:/:/bin/sh
UID >= 60000 ligne 14 : 
clown:*:61000:b:utilisateur en erreur:/home/clown:/bin/sh
Fin 
awk 'BEGIN { print "Verification du fichier /etc/group"; print "le groupe 20 est t-il bien nommé users ? " ; FS=":"}      
     $1 == "users" && $3 ==20 { print "groupe "$1" a le GID "$3" !" }      
     END   { print "Fin" }' /etc/group 
Solution
Verification du fichier /etc/group
le groupe 20 s'appelle t-il bien users ? 
groupe users a le GID 20 ! 
Fin 
awk 'NR == 5 , NR == 10 {print NR" : " $0 }' fichier 
Solution
Imprime de la ligne 5 à la ligne 10 , chaque ligne précédée par son numéro
awk 'BEGIN { FS=":" ; OFS=":"}      
     $NF != "/bin/ksh" { print $0 }      
     $7 == "/bin/ksh" && NF == 7  { $7 = "/bin/posix/sh" ; print $0 } ' /etc/passwd > /etc/passwdnew 
Solution
On crée un nouveau fichier de mot de passe /etc/passwd.new en remplaçant le shell /bin/ksh par /bin/posix/sh