dernière modification : 2023

awk

1. Fonctionnement

awk est un filtre. Il interprête un script de la forme :

condition { action ; action ; action ; ... }
condition { action ; action ; action ; ... }
condition { action ; action ; action ; ... }
...

Pour chacune des lignes de texte du flux vérifiant la condition, les actions associées sont exécutées.

2. Découpage automatique de la ligne courante en champs

Les variables $1, $2 …​ contiennent le champ n°1, n°2 …​ de la ligne courante. $0 correspond à la ligne complète.

donne le login et le temps de connexion des utilisateurs connectés
who | awk '{print $1,$4}'

Le séparateur qui sert au découpage peut être spécifié par l’option -F :

imprime chaque ligne après avoir effacé le deuxième champ
awk -F ":" '{ $2="" ; print $0 }' /etc/passwd

3. Variables

FS

Field Separator

separateur de champs en entrée

OFS

Output Field Separator

separateur de champs en sortie

NF

Number of Fields

nombre de champs de la ligne courante

NR

Number Record

n° de la ligne courante

RS

Record Separator

separateur de ligne en entrée

ORS

Output Record Separator

separateur de ligne en sortie

écrit les lignes de 2 à 10
$ man sed | awk 'NR>2 && NR<10 { print }'   # print est équivalent à print $0
les lignes numérotées
$ awk '{print NR ":", $0}' /etc/passwd

La variable NF contient le nombre de champs de la ligne courante, donc $NF correspond à la valeur du dernier champ :

indice et valeur du dernier champ de chaque ligne
awk '{print NF,$NF}' /etc/mime.types

4. BEGIN et END

Il existe 2 conditions particulières :

  • BEGIN qui est vraie avant l’arrivée de la première ligne, fausse ensuite

  • END qui est vraie après l’envoi de la dernière ligne, fausse avant.

awk workflow
nombre de lignes de f
awk 'END {print NR}' /etc/mime.types
awk 'BEGIN {FS=":";OFS=" -> "}
           {print $5,$1}
' /etc/passwd
fait la somme des tailles des fichiers
$ ls -l | awk 'BEGIN { s=0 }
                     { s=s+$5 }
                END  { print s }'

5. Conditions

sort les variables initialisées dans le fichier
awk -F= '/^[^ ]*=/ {print $1}' /etc/crontab
les lignes de moins de 75 caractères
awk 'length($0)<75 {print}' /etc/services
awk '/^#/    {next}
     $4!="#" {next}
             {$1=$2=$3=$4="";print}
' /etc/protocols
awk 'BEGIN   {OFS=" => "}
     /^#/    {next}
     /^\s*$/ {next}
             {print $2,$3}
' /etc/fstab
écrit toutes les lignes entre 2 lignes déterminée
$ man awk| awk '/^SYNOPSIS$/,/^DESCRIPTION$/ { print}'

6. Exemples plus costauds

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
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

Créer un nouveau fichier de mot de passe /tmp/passwd.new en remplacant le shell /bin/bash par /bin/zsh :

awk 'BEGIN { FS=":" ;
             OFS=":"}
      $NF != "/bin/bash" { print }
      $NF == "/bin/bash" { $NF = "/bin/zsh" ;
                           print }
' /etc/passwd > /tmp/passwd.new