Aller au contenu
Administration Linux medium

Traiter des données avec awk

11 min de lecture

awk est le couteau suisse du traitement de données en ligne de commande. Là où grep filtre des lignes entières et cut extrait des colonnes fixes, awk comprend la structure des données : il découpe chaque ligne en champs, applique des conditions par champ, accumule des valeurs et reformate la sortie. Pas besoin d’un script Python pour calculer le total d’un CSV ou compter les codes d’erreur dans un log — awk fait ça en une ou deux lignes.

C’est un objectif direct LFCS (“Compare and Manipulate File Content”) et RHCSA (“Process text streams using filters”).

  • Accéder aux champs automatiques $1, $NF, NR et NF
  • Changer le séparateur avec -F pour parser :, , ou n’importe quel délimiteur
  • Filtrer des lignes avec des conditions numériques ($3 >= 1000) et des regex ($1 ~ /pattern/)
  • Utiliser BEGIN et END pour afficher des en-têtes et calculer des totaux
  • Construire un tableau associatif pour compter des occurrences par valeur
  • Reformater proprement une sortie avec printf

awk intervient dès que vous avez besoin de raisonner sur la structure d’une ligne plutôt que sur son contenu texte brut :

  • extraire le login et le shell de tous les comptes système depuis /etc/passwd
  • calculer le chiffre d’affaires total depuis un export CSV
  • compter les codes HTTP 4xx et 5xx par IP dans un access.log
  • afficher uniquement les processus d’un utilisateur depuis la sortie de ps
  • reformater une sortie de commande en tableau lisible avec des colonnes alignées

awk n’est pas un langage de script complet comme Python — mais pour les opérations de traitement de flux en ligne de commande, il est plus rapide à écrire, plus lisible qu’un pipeline complexe, et disponible partout.

awk découpe chaque ligne en champs selon un séparateur (espace par défaut) et les numérote :

VariableContenu
$0La ligne entière
$1Premier champ
$2Deuxième champ
$NFDernier champ (NF = nombre de champs)
NRNuméro de la ligne courante
NFNombre de champs sur la ligne courante
Fenêtre de terminal
awk '{print NR, $1, $9}' access.log
1 192.168.1.10 200
2 10.0.0.5 401
3 192.168.1.10 200
4 10.0.0.99 403
5 10.0.0.5 200
6 172.16.0.3 404
7 192.168.1.10 500
  • $1 = adresse IP
  • $9 = code de statut HTTP (le 9e champ dans le format Combined Log)
  • NR = numéro de ligne

Par défaut, awk sépare les champs sur les espaces. L’option -F change ce séparateur :

Fenêtre de terminal
awk -F: '{print $1, $7}' /etc/passwd
root /bin/bash
daemon /usr/sbin/nologin
bob /bin/bash
alice /bin/zsh
sshd /usr/sbin/nologin
  • $1 = nom d’utilisateur
  • $7 = shell de connexion (7e champ séparé par :)
Fenêtre de terminal
# Afficher produit et total (quantité × prix unitaire), en sautant l'en-tête
awk -F, 'NR > 1 {print $1, $3*$4}' ventes.csv
laptop 6000
serveur 7000
switch 4500
laptop 3600
serveur 3500
switch 3600
disque 1600

NR > 1 saute la première ligne (en-tête). Les champs $3 et $4 sont multipliés directement — awk gère l’arithmétique nativement.

Fenêtre de terminal
# Requêtes avec code HTTP >= 400 (erreurs)
awk '$9 >= 400 {print $1, $9, $7}' access.log
10.0.0.5 401 /login
10.0.0.99 403 /admin
172.16.0.3 404 /api/users/42
192.168.1.10 500 /api/orders/7
Fenêtre de terminal
# Requêtes POST seulement
awk '$6 == "\"POST" {print $1, $7, $9}' access.log
10.0.0.5 /login 401
10.0.0.5 /login 200
Fenêtre de terminal
# IPs du réseau 192.168 seulement
awk '$1 ~ /^192\.168\./ {print $1, $9}' access.log
192.168.1.10 200
192.168.1.10 200
192.168.1.10 500
Fenêtre de terminal
# Exclure les requêtes de alice
awk '$3 !~ /alice/ {print $1, $3, $9}' access.log
10.0.0.5 bob 401
10.0.0.99 - 403
10.0.0.5 bob 200
172.16.0.3 charlie 404
  • ~ : le champ correspond au pattern
  • !~ : le champ ne correspond pas au pattern

BEGIN s’exécute avant la première ligne. END s’exécute après la dernière. Utilisés pour les en-têtes, les totaux et les résumés.

Fenêtre de terminal
awk -F, 'NR == 1 { next }
{
total += $3 * $4
lignes++
}
END {
print "Lignes traitées :", lignes
print "Chiffre d'\''affaires total :", total, "€"
}' ventes.csv
Lignes traitées : 7
Chiffre d'affaires total : 29800 €
  • total += $3 * $4 : accumulation dans une variable globale
  • lignes++ : compteur de lignes traitées
  • Le bloc END est appelé une seule fois après toutes les lignes

awk supporte nativement les tableaux dont les clés sont des chaînes — l’outil parfait pour compter des occurrences par valeur.

Fenêtre de terminal
awk '{codes[$9]++} END {for (c in codes) print c, codes[c]}' access.log | sort
200 3
401 1
403 1
404 1
500 1
  • codes[$9]++ : incrémente le compteur indexé par la valeur du code HTTP
  • for (c in codes) : itère sur toutes les clés du tableau
  • | sort : awk ne garantit pas l’ordre des clés — on trie à la fin
Fenêtre de terminal
awk '{ip[$1]++; if ($9 >= 400) err[$1]++}
END {
for (i in ip) printf "%-16s %6d %6d\n", i, ip[i], err[i]+0
}' access.log | sort -k2 -rn
192.168.1.10 3 1
10.0.0.5 2 1
172.16.0.3 1 1
10.0.0.99 1 1
  • Deux tableaux parallèles : ip[] pour le total, err[] pour les erreurs
  • err[i]+0 : si la clé n’existe pas, retourne 0 (pas d’erreur de type)
  • sort -k2 -rn : trier par deuxième colonne (requêtes), décroissant

print sépare les champs avec l’OFS (espace par défaut). printf donne un contrôle précis sur l’alignement et le format.

Fenêtre de terminal
awk -F, 'NR > 1 {printf "%-10s %-6s %6d €\n", $1, $2, $3*$4}' ventes.csv
laptop nord 6000 €
serveur sud 7000 €
switch nord 4500 €
laptop est 3600 €
serveur nord 3500 €
switch sud 3600 €
disque est 1600 €

Formats printf courants :

FormatEffet
%-10sChaîne, alignée à gauche, largeur 10
%10sChaîne, alignée à droite, largeur 10
%6dEntier, largeur 6
%.2fFlottant, 2 décimales
%sChaîne sans largeur fixe
OutilQuand l’utiliser
grepFiltrer des lignes par pattern texte — pas de raisonnement sur les champs
cutExtraire des colonnes à position fixe ou délimiteur simple, sans calcul
sedTransformer du texte, substituer des patterns, modifier in-place
awkFiltrer par champ, calculer, compter, reformater, créer des tableaux de synthèse
PythonLogique complexe, structures de données riches, fichiers JSON/YAML

La règle pratique : si vous avez besoin de raisonner sur la valeur d’un champ (pas juste extraire), commencez par awk.

PiègeSymptômeSolution
Guillemets dans le shell" dans le pattern awk interprété par bashToujours encadrer le programme awk avec des '...'
Confondre print et printfSaut de ligne manquant avec printfAjouter \n explicitement dans printf
Clé inexistante dans un tableauErreur ou valeur videUtiliser arr[k]+0 pour les entiers, arr[k]"" pour les chaînes
Ordre des clés d’un tableauRésultat non triéPiper vers sort après le bloc END
NR vs FNR avec plusieurs fichiersNR continue de s’incrémenter entre fichiersUtiliser FNR pour le numéro de ligne dans le fichier courant
  • $1, $NF, NR — les variables de base à connaître par cœur
  • -F: ou -F, — change le séparateur de champ
  • $3 >= 400 — conditions numériques directes sur un champ
  • $1 ~ /regex/ et $1 !~ /regex/ — filtrage par pattern sur un champ
  • tableau[$clé]++ — compter des occurrences par valeur
  • BEGIN / END — avant la première ligne / après la dernière
  • printf "%-10s %6d\n" — formater une sortie en tableau aligné
  • | sort — toujours trier après for (k in tableau) si l’ordre compte

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn