Aller au contenu
Administration Linux medium

awk : afficher des colonnes et filtrer des lignes

45 min de lecture

Quand vous travaillez avec des fichiers de logs, des exports CSV ou des données tabulaires, vous avez souvent besoin d'extraire des colonnes, de filtrer des lignes ou de calculer des statistiques. awk est un mini-langage de traitement de texte qui lit un fichier ligne par ligne, découpe chaque ligne en champs ($1, $2...), et permet d'appliquer des conditions et des actions sur ces champs.

  • Extraire des colonnes spécifiques d'un fichier
  • Filtrer des lignes selon des conditions (valeur, regex)
  • Effectuer des calculs (somme, moyenne, comptage)
  • Utiliser les blocs BEGIN et END pour structurer vos traitements
  • Manipuler des fichiers CSV avec un séparateur personnalisé

awk fait partie des commandes de traitement de texte sous Linux. Chaque outil a sa spécialité :

CommandeSpécialitéQuand l'utiliser
awkTraiter des données en colonnesExtraire, filtrer, calculer sur des champs
sedÉditer des fichiers en fluxRemplacer du texte, supprimer des lignes
grepRechercher par contenuFiltrer les lignes qui matchent un motif
cutExtraire des colonnes simplesDécoupage basique par délimiteur
sort / uniqTrier et dédupliquerClassement, comptage d'occurrences
xargsExécuter en massePasser des lignes à une commande

Combinaisons de commandes fréquentes :

La commande awk est souvent utilisée en combinaison avec d'autres outils pour des traitements plus complexes :

Fenêtre de terminal
# awk + sort : trier les résultats d'awk
awk -F';' '{ print $2, $3 }' ventes.csv | sort -k2 -n
# grep + awk : filtrer puis extraire
grep "ERROR" app.log | awk '{ print $1, $NF }'
# awk + xargs : traitement en masse
awk '/pattern/ { print $1 }' fichier | xargs commande

🧠 Modèle mental — Comment fonctionne awk

awk = Pour chaque ligne → Si condition vraie → Exécuter action

Modèle mental awk : Entrée (fichier/stdin) → Condition (motif /regex/, $2>100) → Action ({print $1}) + Blocs spéciaux BEGIN/END

Points clés

  • awk lit le fichier ligne par ligne automatiquement
  • Chaque ligne est découpée en champs : $1, $2, $3... ($0 = ligne entière)
  • Par défaut, le séparateur est l'espace ou la tabulation
  • Sans condition, l'action s'applique à TOUTES les lignes
  • BEGIN s'exécute AVANT de lire le fichier (init)
  • END s'exécute APRÈS avoir lu tout le fichier (bilan, totaux)

Règles d'or

1
Toujours définir -F pour les CSV Par défaut awk sépare sur les espaces. Pour un CSV : awk -F';'...
2
Tester sur quelques lignes d'abord Utilise head -5 fichier | awk '...' pour vérifier ta commande.

Vocabulaire essentiel

$0
La ligne entière
$1, $2, $N
Champ 1, 2, N de la ligne
$NF
Dernier champ de la ligne
NR
Numéro de la ligne courante
NF
Nombre de champs dans la ligne
FS
Field Separator (séparateur de champs)
📚 Pour aller plus loin — 12 options avancées
OFS
Output Field Separator (séparateur de sortie)
RS
Record Separator (séparateur d'enregistrements)
ORS
Output Record Separator
FILENAME
Nom du fichier en cours de traitement
FNR
Numéro de ligne dans le fichier courant
gsub()
Remplacer toutes les occurrences
sub()
Remplacer la première occurrence
split()
Découper une chaîne en tableau
length()
Longueur d'une chaîne
substr()
Extraire une sous-chaîne
printf
Affichage formaté (comme en C)
arrays[]
Tableaux associatifs (clé/valeur)

Contrairement à grep (qui filtre des lignes) ou sed (qui modifie en flux), awk est un vrai langage qui permet de traiter chaque ligne comme un enregistrement avec des champs numérotés.

Deux formes d'appel coexistent, et le choix se fait sur la longueur du programme. En ligne de commande, tout tient entre guillemets simples, obligatoires pour empêcher le shell de remplacer $1 par un argument positionnel avant qu'awk ne le voie. Au-delà de quelques lignes, passez par un fichier .awk avec l'option -f : vous récupérez l'indentation, les commentaires et la coloration syntaxique de votre éditeur.

Fenêtre de terminal
awk [options] 'programme' fichier(s) # programme écrit dans la ligne de commande, pour les cas simples
awk [options] -f script.awk fichier(s) # programme awk lu depuis un fichier externe

Structure du programme :

Fenêtre de terminal
awk 'BEGIN { init } condition { action } END { final }' fichier

Options principales :

OptionDescriptionExemple
-F sepDéfinit le séparateur de champsawk -F';' '...' (CSV)
-v var=valDéfinit une variable avant l'exécutionawk -v seuil=100 '$2 > seuil'
-f scriptLit le programme depuis un fichierawk -f analyse.awk data.txt

Formes courantes :

Fenêtre de terminal
# Forme minimale : action sur toutes les lignes
awk '{ print $1 }' fichier
# Avec condition : filtrer les lignes
awk '/pattern/ { print }' fichier
awk '$3 > 100 { print $1, $3 }' fichier
# Avec blocs BEGIN/END : initialisation et finalisation
awk 'BEGIN { FS=";" } { sum += $2 } END { print sum }' fichier
# Depuis un pipe
cat fichier | awk '{ print $NF }'
# Plusieurs fichiers
awk '{ print FILENAME, $0 }' fichier1 fichier2

La commande awk suit toujours la même logique :

PartieQuestionExemplesObligatoire ?
EntréeQuel fichier ou flux traiter ?fichier.txt, stdinFichier ou pipe
Condition (motif)Quelles lignes traiter ?/ERROR/, $3 > 100, NR > 1Non (par défaut : toutes)
ActionQue faire sur ces lignes ?{ print $1 }, { sum += $2 }Non (par défaut : { print })

Entrée, awk lit le fichier ou le flux ligne par ligne. Chaque ligne est automatiquement découpée en champs selon le séparateur (espace par défaut).

Condition (optionnelle), Si vous ne mettez pas de condition, l'action s'applique à toutes les lignes. Sinon, seules les lignes qui matchent sont traitées.

Action (optionnelle), Entre accolades { }. Sans action explicite, awk fait { print } (affiche la ligne).

Les variables intégrées : comprendre le découpage

Section intitulée « Les variables intégrées : comprendre le découpage »

awk découpe automatiquement chaque ligne en champs numérotés, sans que vous ayez à écrire la moindre ligne de code pour cela. Deux variables du tableau se distinguent des autres et méritent d'être mémorisées en premier : NF compte les champs de la ligne courante, et $NF désigne donc le dernier champ quel que soit le nombre de colonnes. C'est ce qui permet de traiter des lignes de longueur variable, cas courant dans les journaux système. Ne confondez pas NR (le numéro de ligne) avec NF (le nombre de champs) : l'inversion des deux est l'erreur de frappe la plus fréquente chez les débutants.

VariableSignificationExemple
$0La ligne entièreprint $0
$1, $2, $NChamp 1, 2, Nprint $1, $3
$NFDernier champprint $NF
NRNuméro de ligne (global)NR > 1 (sauter en-tête)
NFNombre de champsNF >= 3
FSSéparateur d'entréeBEGIN { FS=";" }

Exemple concret :

Fenêtre de terminal
# Fichier : "Alice 25 Paris"
# $1=Alice, $2=25, $3=Paris, NF=3
awk '{ print $1, "a", $2, "ans" }' fichier.txt
# Résultat : Alice a 25 ans

Par défaut, awk sépare sur les espaces et tabulations. Pour un CSV :

Fenêtre de terminal
# Fichier CSV avec séparateur ;
awk -F';' '{ print $1, $3 }' ventes.csv
# Équivalent avec BEGIN
awk 'BEGIN { FS=";" } { print $1, $3 }' ventes.csv

Attention : Piège courant : si $2 est vide ou incorrect, vérifiez que vous avez bien défini -F !

Les conditions permettent de sélectionner les lignes sur lesquelles appliquer l'action. Repérez la différence entre les deux dernières familles du tableau : /pattern/ teste la ligne entière, alors que $N ~ /regex/ restreint le test à un champ précis. Cette précision évite les faux positifs, par exemple quand vous cherchez un code d'erreur qui pourrait aussi apparaître dans une URL. La condition NR > 1, elle, ne teste aucun contenu : elle sert uniquement à écarter la ligne d'en-tête d'un fichier CSV, geste à faire systématiquement avant tout calcul.

ConditionCe qu'elle testeExemple
$N == "val"Égalité stricte$1 == "admin"
$N != "val"Différent de$3 != "OK"
$N > valSupérieur (numérique)$2 > 100
$N ~ /regex/Matche la regex$1 ~ /^192/
$N !~ /regex/Ne matche pas$4 !~ /error/
/pattern/Pattern sur toute la ligne/ERROR/
NR > 1À partir de la ligne 2Sauter l'en-tête CSV

Combiner les conditions, ET (&&) / OU (||) / NON (!) :

Fenêtre de terminal
# ET : les deux conditions doivent être vraies
awk '$2 > 100 && $3 == "OK" { print }' fichier.txt
# OU : au moins une condition vraie
awk '$1 == "admin" || $1 == "root" { print }' fichier.txt
# NON : inverser une condition
awk '!($3 ~ /error/) { print }' fichier.txt

Les actions : que faire des lignes sélectionnées ?

Section intitulée « Les actions : que faire des lignes sélectionnées ? »

Une fois les lignes filtrées, vous pouvez agir dessus. Les deux premières actions du tableau affichent quelque chose immédiatement, les deux suivantes accumulent en mémoire sans rien produire avant le bloc END. Cette distinction explique un étonnement classique : un programme qui ne contient que { sum += $2 } n'affiche rien du tout, puisque personne ne demande jamais le résultat. Les variables d'awk n'ont d'ailleurs pas besoin d'être déclarées : elles valent 0 ou la chaîne vide à leur première utilisation, ce qui permet d'écrire sum += $2 sans initialisation préalable.

ActionCe qu'elle faitExemple
{ print }Affiche la ligne (défaut){ print }
{ print $1, $3 }Affiche certains champs{ print $1, $3 }
{ sum += $2 }Accumule dans une variableCalcul de total
{ count[$1]++ }Tableau associatifComptage par clé
{ next }Passe à la ligne suivanteIgnorer cette ligne

awk propose deux blocs qui s'exécutent avant et après le traitement du fichier. Ils s'exécutent une seule fois, contrairement au corps du programme qui tourne à chaque ligne. BEGIN sert à préparer le terrain, en général définir FS ou afficher un titre de rapport, et il s'exécute même si le fichier est vide ou absent. END sert à restituer ce qui a été accumulé : c'est là que se rendent les totaux, les moyennes et le parcours des tableaux associatifs.

Fenêtre de terminal
awk 'BEGIN { actions_init } condition { actions } END { actions_fin }' fichier
BlocQuand s'exécuteCas d'usage
BEGIN { }Avant de lire le fichierDéfinir FS, afficher un titre
END { }Après avoir lu tout le fichierAfficher un total, une moyenne

Exemple complet, Rapport avec total :

Fenêtre de terminal
awk -F';' '
BEGIN { print "=== Rapport ===" }
NR > 1 { total += $3; print $1, $3 }
END { print "Total:", total }
' ventes.csv

awk excelle pour les statistiques simples sur des fichiers. Les quatre exemples ci-dessous partagent la même structure : accumuler dans le corps, restituer dans END. Deux précautions valent pour tous. Ajoutez NR > 1 dès que le fichier possède un en-tête, sinon une ligne de texte entre dans le calcul avec la valeur 0 et fausse la moyenne. Protégez également la division : si aucune ligne n'est traitée, n vaut 0 et awk s'arrête sur une erreur fatale division by zero attempted.

Fenêtre de terminal
# Somme d'une colonne
awk '{ sum += $2 } END { print "Total:", sum }' fichier.txt
# Moyenne
awk '{ sum += $2; n++ } END { print "Moyenne:", sum/n }' fichier.txt
# Min et Max
awk 'NR == 1 || $2 > max { max = $2 } END { print "Max:", max }' fichier.txt
# Comptage de lignes selon une condition
awk '$3 == "OK" { count++ } END { print "OK:", count }' fichier.txt

Les tableaux associatifs sont la fonctionnalité la plus puissante de awk pour l'analyse : ils remplacent à eux seuls un sort | uniq -c et gèrent des agrégations que ces outils ne savent pas faire. La syntaxe count[$1]++ crée la clé si elle n'existe pas et incrémente sinon, en une seule expression. Un point de vigilance sur le parcours : for (k in arr) restitue les clés dans un ordre non garanti, qui n'est ni l'ordre d'apparition ni l'ordre alphabétique. Pour un résultat classé, passez la sortie à sort, comme le montre le troisième exemple.

Fenêtre de terminal
# Compter les occurrences par valeur
awk '{ count[$1]++ } END { for (k in count) print k, count[k] }' access.log
# Somme par catégorie
awk -F';' '{ ventes[$4] += $2 } END { for (v in ventes) print v, ventes[v] }' data.csv
# Combiner avec un tri externe
awk '{ count[$1]++ } END { for (k in count) print k, count[k] }' log | sort -k2 -rn

print ajoute automatiquement des espaces et un retour à la ligne. printf offre un contrôle précis de la largeur des colonnes, ce qui devient indispensable dès qu'on produit un rapport lisible plutôt qu'une simple extraction. Le principe est celui du printf du langage C : une chaîne de format contenant des marqueurs, puis les valeurs dans l'ordre. Retenez que la largeur s'exprime en caractères et que le signe moins aligne à gauche : %-15s réserve quinze positions et complète par des espaces à droite.

Fenêtre de terminal
# Alignement et format
awk '{ printf "%-15s %8.2f€\n", $1, $2 }' prix.txt
# Tableau formaté
awk 'BEGIN { printf "%-10s %s\n", "Nom", "Valeur" }
{ printf "%-10s %d\n", $1, $2 }' fichier.txt
FormatSignificationExemple
%sChaîneprintf "%s", $1
%dEntierprintf "%5d", $2 (5 caractères)
%.2fDécimal 2 chiffresprintf "%.2f", $3
%-10s10 caractères, aligné gaucheprintf "%-10s", $1
\nRetour à la ligneObligatoire avec printf !

Attention : Piège : printf ne met pas de retour à la ligne automatiquement. Ajoutez \n !

Ces cinq situations couvrent l'essentiel des programmes awk qui « ne marchent pas ». Aucune ne produit de message d'erreur : la commande s'exécute et rend un résultat faux, ce qui est bien plus coûteux à repérer qu'un plantage. Le réflexe de diagnostic est toujours le même, afficher NF et $0 pour vérifier le découpage réel avant de suspecter la logique du programme.

ErreurCauseSolution
$2 est vide ou incorrectMauvais séparateurDéfinir -F';' pour CSV
Le shell interprète $1Doubles guillemetsUtiliser des guillemets simples : awk '...'
L'en-tête est inclus dans les calculsPas de filtreAjouter NR > 1
printf colle tout sur une lignePas de \nAjouter \n à la fin du format
Comparaison string au lieu de nombre"9" > "100" est vrai (string)Forcer avec ($2 + 0) > 100

Maintenant que vous comprenez awk, voici dix modèles prêts à l'emploi, du plus simple au plus avancé. Chacun donne sa formule générale et un exemple concret.

Afficher un champ précis de chaque ligne. Un numéro de champ qui n'existe pas ne provoque pas d'erreur : awk renvoie une chaîne vide, ce qui produit des lignes blanches plutôt qu'un message explicite.

Fenêtre de terminal
awk '{ print $N }' fichier # formule
awk '{ print $2 }' fichier.txt # exemple
  • $N : numéro du champ (1, 2, 3…)
  • $0 : la ligne entière
  • $NF : le dernier champ

Lire un fichier avec un séparateur personnalisé. Cette forme ne gère pas les champs quotés contenant le séparateur ("Dupont, Jean") : pour un CSV complexe, passez par un vrai analyseur plutôt que par awk.

Fenêtre de terminal
awk -F'<sep>' '{ print $1, $3 }' fichier.csv # formule
awk -F';' '{ print $1, $3 }' ventes.csv # exemple
  • -F : définit le séparateur de champs
  • ; : séparateur CSV (ou ,, ou \t)

N'afficher que les lignes qui remplissent une condition. La condition se place avant les accolades ; à l'intérieur, elle deviendrait une simple expression sans effet sur la sélection des lignes.

Fenêtre de terminal
awk '<condition> { action }' fichier # formule
awk '$3 > 100 { print $1, $3 }' fichier.txt # exemple
  • $N == "val" : égalité stricte
  • $N > val : comparaison numérique
  • $N ~ /regex/ : correspondance d'une expression régulière

Ignorer la première ligne, les en-têtes d'un fichier CSV. Avec plusieurs fichiers en argument, NR continue de compter sans se réinitialiser : utilisez alors FNR > 1, qui repart à zéro à chaque fichier.

Fenêtre de terminal
awk 'NR > 1 { action }' fichier # formule
awk -F';' 'NR > 1 { print $1 }' data.csv # exemple
  • NR : numéro de ligne courant (1, 2, 3…)
  • NR > 1 : à partir de la ligne 2

Calculer le total d'une colonne numérique. La variable sum n'a pas besoin d'être déclarée : elle vaut 0 à sa première utilisation. Ajoutez NR > 1 si le fichier possède un en-tête.

Fenêtre de terminal
awk '{ sum += $N } END { print sum }' fichier # formule
awk '{ sum += $2 } END { print sum }' ventes.txt # exemple
  • sum += $N : accumule la valeur dans une variable
  • END : bloc exécuté après la lecture du fichier

Moyenne d'une colonne. Le compteur n est indispensable, car NR compterait aussi les lignes ignorées par la condition. Protégez la division si le fichier peut être vide.

Fenêtre de terminal
awk '{ sum += $N; n++ } END { print sum/n }' fichier # formule
awk 'NR > 1 { sum += $3; n++ } END { print sum/n }' data.csv # exemple
  • n++ : compte le nombre de lignes traitées
  • sum/n : moyenne = total ÷ nombre

Regrouper et compter les occurrences avec un tableau associatif. C'est l'équivalent d'un GROUP BY en une ligne. L'ordre de sortie n'est pas garanti : ajoutez | sort pour un résultat stable.

Fenêtre de terminal
awk '{ count[$1]++ } END { for (k in count) print k, count[k] }' fichier # formule
awk '{ count[$1]++ } END { for (ip in count) print ip, count[ip] }' access.log # exemple
  • count[$1]++ : tableau associatif indexé par $1
  • for (k in arr) : parcourt les clés du tableau

Additionner une valeur par catégorie. Le même tableau peut porter plusieurs agrégats en parallèle (un pour la somme, un pour le compte), ce qui permet de calculer une moyenne par groupe dans le bloc END.

Fenêtre de terminal
awk '{ total[$1] += $2 } END { for (k in total) print k, total[k] }' fichier # formule
awk -F';' '{ vente[$4] += $2 } END { for (v in vente) print v, vente[v] }' data.csv # exemple
  • total[$1] += $2 : accumule la valeur de $2 par clé $1

Sélectionner les lignes qui correspondent à un motif. Le motif s'écrit entre slashes, sans guillemets. Écrire "/ERROR/" transformerait la regex en simple chaîne, toujours vraie, et toutes les lignes ressortiraient.

Fenêtre de terminal
awk '/<pattern>/ { action }' fichier # formule
awk '/ERROR|WARN/ { print }' app.log # exemple
  • /regex/ : motif testé sur la ligne entière
  • $N ~ /regex/ : motif testé sur un champ précis
  • !~ : l'inverse, ne correspond pas

Afficher avec un alignement et un format précis. Le nombre de marqueurs doit correspondre au nombre de valeurs fournies : un marqueur en trop affiche une valeur vide ou un zéro, sans le moindre avertissement.

Fenêtre de terminal
awk '{ printf "%-10s %5d\n", $1, $2 }' fichier # formule
awk '{ printf "%-15s %8.2f€\n", $1, $2 }' prix.txt # exemple
  • %-10s : chaîne sur 10 caractères, alignée à gauche
  • %5d : entier sur 5 caractères
  • %.2f : décimal avec 2 chiffres après la virgule

Six erreurs reviennent constamment avec awk. Pour chacune : la commande piégée, le symptôme, la cause et la correction.

Fenêtre de terminal
awk '{ print $2 }' fichier.csv # INCORRECT : affiche la ligne entière

Symptôme : $2 est vide ou ne contient pas ce qu'on attend. Cause : le fichier utilise ; ou ,, mais awk découpe sur les espaces par défaut.

Fenêtre de terminal
awk -F';' '{ print $2 }' fichier.csv # CORRECT : séparateur explicite
Fenêtre de terminal
awk "{ print $1 }" fichier # INCORRECT : le shell remplace $1 avant awk

Symptôme : résultat vide ou inattendu. Cause : les guillemets doubles laissent le shell interpréter les $.

Fenêtre de terminal
awk '{ print $1 }' fichier # CORRECT : guillemets simples : awk reçoit le programme intact

Encadrez toujours le programme awk de guillemets simples.

Fenêtre de terminal
awk -F';' '{ sum += $2 } END { print sum }' data.csv # INCORRECT : résultat faux

Symptôme : le total ou la moyenne est incorrect. Cause : la ligne d'en-tête (du texte) est ajoutée au calcul, où elle vaut 0.

Fenêtre de terminal
awk -F';' 'NR > 1 { sum += $2 } END { print sum }' data.csv # CORRECT : en-tête ignoré
Fenêtre de terminal
awk '$2 > "100"' fichier # INCORRECT : "9" > "100" est vrai en comparaison de chaînes

Symptôme : une ligne dont le champ vaut 9 ressort alors que vous cherchiez les valeurs supérieures à 100. Cause : dès qu'un des deux opérandes est une constante entre guillemets, awk bascule en comparaison lexicographique, et "9" passe après "100" dans l'ordre des caractères. Le même piège se déclenche si le champ contient autre chose qu'un nombre, par exemple une unité collée (100Mo) ou un séparateur de milliers.

Fenêtre de terminal
awk '$2 > 100' fichier # CORRECT : constante numérique, comparaison numérique
awk '($2 + 0) > 100' fichier # CORRECT : le + 0 force le contexte numérique

Sans guillemets autour de 100, awk applique ses règles de strnum : un champ qui ressemble à un nombre est traité comme tel, la comparaison est donc bien numérique. Le + 0 reste utile pour les champs douteux, puisqu'il convertit explicitement et rend l'intention visible à la relecture.

Fenêtre de terminal
awk '$3 > 100' fichier # Attention : fonctionne, mais peu lisible

Symptôme : la commande affiche des lignes sans action visible. Cause : sans { }, awk applique { print } par défaut, un comportement implicite peu clair.

Fenêtre de terminal
awk '$3 > 100 { print }' fichier # CORRECT : action explicite
Fenêtre de terminal
awk '{ printf "%s %s", $1, $2 }' fichier # INCORRECT : toute la sortie sur une seule ligne

Symptôme : la sortie est collée, sans retours à la ligne. Cause : contrairement à print, printf n'ajoute pas de saut de ligne automatiquement.

Fenêtre de terminal
awk '{ printf "%s %s\n", $1, $2 }' fichier # CORRECT : \n explicite en fin de format

Rien ne remplace la pratique. Créez l'environnement de test ci-dessous, puis déroulez les huit étapes. À la fin, nettoyez avec rm -rf ~/awk-lab.

Ce script crée quatre fichiers de test dans ~/awk-lab : un CSV de ventes, un log Apache, un relevé de notes et un fichier d'employés.

Fenêtre de terminal
# Créer le lab
mkdir -p ~/awk-lab
cd ~/awk-lab
# Fichier CSV avec séparateur ;
cat > ventes.csv << 'EOF'
produit;quantite;prix_unitaire;vendeur
laptop;5;899.99;Alice
souris;50;19.99;Bob
clavier;30;49.99;Alice
ecran;10;299.99;Charlie
laptop;3;899.99;Bob
souris;100;19.99;Alice
EOF
# Fichier de logs Apache
cat > access.log << 'EOF'
192.168.1.10 - - [01/Jan/2024:10:00:00] "GET /index.html HTTP/1.1" 200 1234
192.168.1.20 - - [01/Jan/2024:10:01:15] "GET /api/users HTTP/1.1" 200 567
192.168.1.10 - - [01/Jan/2024:10:02:30] "POST /api/login HTTP/1.1" 401 89
192.168.1.30 - - [01/Jan/2024:10:03:45] "GET /index.html HTTP/1.1" 200 1234
192.168.1.20 - - [01/Jan/2024:10:04:00] "GET /api/users HTTP/1.1" 500 45
192.168.1.10 - - [01/Jan/2024:10:05:10] "GET /images/logo.png HTTP/1.1" 200 5678
EOF
# Fichier de notes d'étudiants
cat > notes.txt << 'EOF'
Alice 15 18 12
Bob 10 14 16
Charlie 18 17 19
Diana 12 11 13
Eve 20 19 18
EOF
# Fichier avec espaces (plus complexe)
cat > employes.txt << 'EOF'
Jean Dupont;Développeur;45000
Marie Martin;Chef de projet;55000
Pierre Durand;Administrateur;50000
Sophie Bernard;Développeur;48000
EOF
echo "Lab créé dans ~/awk-lab"
ls -la ~/awk-lab

Ces huit commandes ne modifient aucun fichier : elles affichent leur résultat à l'écran, vous pouvez donc les rejouer autant de fois que nécessaire. La progression suit l'ordre dans lequel on construit un traitement réel : d'abord découper correctement, ensuite filtrer, enfin calculer et formater. Comparez systématiquement la sortie obtenue au résultat annoncé ; un écart signale presque toujours un problème de séparateur ou de numéro de champ.

  1. Afficher une colonne spécifique. Affiche uniquement la première colonne (produit) du fichier CSV.

    Fenêtre de terminal
    awk -F';' '{ print $1 }' ~/awk-lab/ventes.csv

    Résultat attendu : la liste des produits (laptop, souris, clavier, ecran…). -F';' définit le séparateur, $1 cible le premier champ.

  2. Sauter l'en-tête. Affiche les produits sans la ligne d'en-tête.

    Fenêtre de terminal
    awk -F';' 'NR > 1 { print $1 }' ~/awk-lab/ventes.csv

    NR est le numéro de ligne ; NR > 1 saute la première ligne (produit).

  3. Filtrer par valeur. Affiche uniquement les ventes réalisées par Alice.

    Fenêtre de terminal
    awk -F';' '$4 == "Alice" { print }' ~/awk-lab/ventes.csv

    $4 == "Alice" teste si le quatrième champ vaut exactement Alice, trois lignes correspondent.

  4. Calculer un total. Calcule le total des quantités vendues.

    Fenêtre de terminal
    awk -F';' 'NR > 1 { total += $2 } END { print total }' ~/awk-lab/ventes.csv

    Résultat attendu : 198 (5+50+30+10+3+100). total += $2 accumule, END affiche après la lecture.

  5. Calculer une moyenne. Calcule la moyenne des trois notes de chaque étudiant.

    Fenêtre de terminal
    awk '{ moy = ($2 + $3 + $4) / 3; print $1, moy }' ~/awk-lab/notes.txt

    On effectue le calcul directement dans awk. Pas besoin de -F ici : le séparateur par défaut (l'espace) convient.

  6. Compter par catégorie. Compte le nombre de ventes par vendeur.

    Fenêtre de terminal
    awk -F';' 'NR > 1 { count[$4]++ } END { for (v in count) print v, count[v] }' ~/awk-lab/ventes.csv

    Résultat attendu : Alice 3, Bob 2, Charlie 1. count[$4]++ utilise un tableau associatif indexé par le vendeur.

  7. Filtrer avec une expression régulière. Affiche les lignes du log contenant une erreur (code HTTP 4xx ou 5xx).

    Fenêtre de terminal
    awk '$8 ~ /^[45]/ { print }' ~/awk-lab/access.log

    Résultat attendu : deux lignes, les codes 401 et 500. Comptez les champs avant d'écrire la commande : sur ce format de log, $8 porte le code HTTP et $9 la taille de la réponse. Sur un journal Apache complet, l'horodatage contient un fuseau ([01/Jan/2024:10:00:00 +0100]) qui ajoute un champ et décale tout d'un rang. La commande awk '{ print NF, $0 }' lève le doute en une seconde.

  8. Formater la sortie. Affiche les employés avec leur salaire suivi du symbole €, en colonnes alignées.

    Fenêtre de terminal
    awk -F';' '{ printf "%-20s %s€\n", $1, $3 }' ~/awk-lab/employes.txt

    printf permet un formatage précis : %-20s réserve 20 caractères alignés à gauche.

Huit exercices pour valider votre maîtrise, du plus simple au plus complet. Tous se traitent sur les fichiers du lab ~/awk-lab (ou sur /etc/passwd). Cherchez d'abord par vous-même, puis dépliez la solution pour vous corriger.

Ces trois exercices portent sur le geste de base : découper et afficher. Deux d'entre eux utilisent /etc/passwd, un fichier présent sur toutes les distributions et séparé par des deux-points, ce qui oblige à penser à l'option -F dès la première commande. Vérifiez votre résultat en le comparant à cut -d: -f7 /etc/passwd : les deux outils doivent produire exactement la même sortie.

Exercice 1, Afficher la dernière colonne. Affichez la dernière colonne de chaque ligne de /etc/passwd. Indice : $NF représente le dernier champ.

Voir la solution
Fenêtre de terminal
awk -F':' '{ print $NF }' /etc/passwd

/etc/passwd utilise : comme séparateur ; $NF cible le dernier champ, le shell de chaque utilisateur.

Exercice 2, Filtrer les utilisateurs avec un shell. Affichez les utilisateurs dont le shell est /bin/bash. Indice : filtrez sur $7.

Voir la solution
Fenêtre de terminal
awk -F':' '$7 == "/bin/bash" { print $1 }' /etc/passwd

$7 est le champ shell dans /etc/passwd ; on teste l'égalité stricte, puis on affiche le nom ($1).

Exercice 3, Numéroter les lignes. Affichez chaque ligne du fichier notes.txt précédée de son numéro. Indice : NR contient le numéro de ligne.

Voir la solution
Fenêtre de terminal
awk '{ print NR, $0 }' ~/awk-lab/notes.txt

NR = numéro de ligne courant, $0 = ligne entière.

On passe ici à l'accumulation : le résultat ne s'affiche plus ligne par ligne mais une seule fois, dans le bloc END. Les deux exercices exigent de sauter l'en-tête ou de maîtriser le formatage. Si votre total paraît trop élevé de quelques unités, l'en-tête a probablement été compté ; s'il est décimal alors que vous attendiez un entier, vérifiez la colonne visée.

Exercice 4, Total d'une colonne CSV. Calculez le total de la colonne prix_unitaire de ventes.csv (séparateur ;). Indice : accumulez avec += et affichez dans END.

Voir la solution
Fenêtre de terminal
awk -F';' 'NR > 1 { total += $3 } END { print total }' ~/awk-lab/ventes.csv

NR > 1 saute l'en-tête ; le bloc END s'exécute après la lecture complète.

Exercice 5, Moyenne avec formatage. Calculez la moyenne de la colonne 2 de notes.txt et affichez-la avec 2 décimales. Indice : printf "%.2f".

Voir la solution
Fenêtre de terminal
awk '{ sum += $2; n++ } END { printf "Moyenne : %.2f\n", sum/n }' ~/awk-lab/notes.txt

printf formate la sortie ; %.2f impose deux décimales.

Ces deux exercices reproduisent une analyse de journal réelle : agréger par clé et isoler les erreurs. Le premier introduit le tableau associatif, le second demande de repérer le bon champ avant d'écrire la regex. Aucun des deux ne se résout de tête : commencez par afficher les champs numérotés pour situer l'information.

Exercice 6, Compter les requêtes par IP. Comptez combien de requêtes chaque IP a faites dans access.log. Indice : tableau associatif indexé par $1.

Voir la solution
Fenêtre de terminal
awk '{ count[$1]++ } END { for (ip in count) print ip, count[ip] }' ~/awk-lab/access.log

count[$1]++ crée un compteur par IP ; for (k in arr) parcourt les clés.

Exercice 7, Filtrer les erreurs HTTP. Affichez uniquement les lignes d'access.log dont le code HTTP est une erreur (4xx ou 5xx). Indice : commencez par compter les champs avec awk '{ print NF, $0 }' pour situer le code.

Voir la solution
Fenêtre de terminal
awk '$8 ~ /^[45][0-9][0-9]$/ { print }' ~/awk-lab/access.log

~ teste une expression régulière ; ^[45][0-9][0-9]$ impose exactement trois chiffres commençant par 4 ou 5. Le code se trouve en $8 sur ce fichier : $9 contient la taille de la réponse, et le filtrer donnerait des lignes en 200.

Le dernier exercice combine tout : BEGIN pour l'en-tête, le corps pour les données et l'accumulation, END pour le total. C'est la structure exacte de n'importe quel rapport produit avec awk, et savoir l'écrire de mémoire constitue un bon critère de maîtrise. Soignez l'alignement : des largeurs identiques entre l'en-tête et les lignes de données font toute la lisibilité.

Exercice 8, Rapport formaté avec totaux. Générez, à partir de ventes.csv, un rapport avec en-tête, données alignées et total final. Indice : BEGIN pour l'en-tête, printf pour l'alignement, END pour le total.

Voir la solution
Fenêtre de terminal
awk -F';' '
BEGIN { printf "%-15s %10s\n", "Produit", "Prix" }
NR > 1 { printf "%-15s %10.2f\n", $1, $3; total += $3 }
END { printf "%-15s %10.2f\n", "TOTAL", total }
' ~/awk-lab/ventes.csv

BEGIN pose les titres, le corps traite chaque ligne, END affiche le bilan, la structure type d'un rapport awk.

Quand un programme awk ne donne pas le résultat attendu, le problème vient presque toujours du découpage en champs. Voici comment diagnostiquer.

Ces quatre commandes répondent à une seule question, posée dans l'ordre : qu'est-ce qu'awk voit réellement ? La deuxième est la plus rentable, car un NF inattendu révèle immédiatement un mauvais séparateur ou des lignes irrégulières. La troisième numérote chaque champ et sert quand vous ne savez plus dans quelle colonne se trouve l'information cherchée. La quatrième limite le travail à quelques lignes, réflexe utile sur un journal de plusieurs gigaoctets.

Fenêtre de terminal
# Voir ce qu'awk reçoit réellement (numéro de ligne + ligne)
awk '{ print NR, $0 }' fichier
# Vérifier le nombre de champs détectés sur chaque ligne
awk '{ print NF, $0 }' fichier
# Afficher chaque champ séparément, numéroté
awk -F';' '{ for (i=1; i<=NF; i++) print i, $i }' fichier
# Tester sur quelques lignes seulement, sans traiter tout le fichier
head -5 fichier | awk '...'

Contrairement aux erreurs de logique vues plus haut, ces trois cas provoquent un message explicite et un code de retour non nul. awk indique le numéro de ligne du programme fautif, ce qui aide surtout quand le programme est dans un fichier .awk. La division par zéro est particulièrement traître : elle survient dans le bloc END après un traitement apparemment réussi, quand aucune ligne n'a alimenté le compteur.

Message d'erreurCause probableSolution
awk: syntax error at source line 1Guillemets ou accolades { } mal fermésVérifier que les guillemets simples encadrent tout le programme et que chaque { a son }
awk: illegal field $()Le shell a interprété $1 avant awkEncadrer le programme de guillemets simples : awk '...', jamais awk "..."
awk: division by zeroLe diviseur vaut 0 (fichier vide, compteur nul)Protéger le calcul : END { if (n > 0) print sum/n }

Les cinq tableaux qui suivent rassemblent ce qui sert au quotidien, classé par nature. Ils sont pensés pour la consultation rapide en cours de rédaction d'une commande, pas pour l'apprentissage : si un élément vous surprend, revenez à la section correspondante plus haut.

Les trois formes ci-dessous couvrent tous les usages. La troisième est la structure complète, celle vers laquelle tend n'importe quel traitement un peu ambitieux : initialiser, traiter chaque ligne, conclure. Notez que les blocs sont tous facultatifs et peuvent apparaître dans n'importe quel ordre, même si l'ordre naturel reste le plus lisible.

ÉlémentRôleExemple
awk [options] '{ programme }' fichier(s)Format général de la commandeawk '{ print $1 }' data.txt
awk [options] -f script.awk fichier(s)Programme lu depuis un fichier externeawk -f analyse.awk data.csv
awk 'BEGIN {…} condition {…} END {…}' fichierStructure complète avec blocs spéciauxawk 'BEGIN{s=0} {s+=$1} END{print s}'

Trois options suffisent en pratique. -F définit le séparateur d'entrée et remplace un BEGIN { FS=";" } plus verbeux. L'option -v est la seule façon propre de faire entrer une valeur du shell dans le programme : elle évite d'ouvrir des guillemets doubles, donc de laisser le shell interpréter les $. Elle s'utilise aussi pour redéfinir une variable interne, par exemple -v OFS=",".

OptionRôleExemple
-F sepDéfinit le séparateur de champsawk -F';' '...' data.csv
-v var=valDéfinit une variable avant l'exécutionawk -v seuil=100 '$2 > seuil'
-f script.awkLit le programme depuis un fichierawk -f analyse.awk data.txt

Ces variables sont mises à jour automatiquement à chaque ligne lue, vous n'avez jamais à les alimenter. La distinction à retenir oppose FS, le séparateur en entrée, à OFS, le séparateur en sortie. Redéfinir OFS n'a d'effet que si vous utilisez la virgule dans un print : print $1, $2 respecte OFS, alors que print $1 $2 colle les deux champs sans rien insérer.

VariableRôleExemple
$0La ligne entièreprint $0
$1, $2, $NChamp 1, 2, Nprint $1, $3
$NFLe dernier champprint $NF
NRNuméro de ligne (global)NR > 1
NFNombre de champs de la ligneNF >= 3
FSSéparateur d'entréeBEGIN { FS=";" }
OFSSéparateur de sortieBEGIN { OFS="," }

Toute condition d'awk se ramène à une expression qui vaut vrai ou faux, ce qui autorise à les combiner librement avec &&, || et la négation !. Attention à la comparaison d'égalité : == compare, = affecte. Écrire $1 = "admin" remplace le premier champ au lieu de le tester, et le programme s'exécute sans la moindre erreur en réécrivant vos données.

ConditionRôleExemple
$N == "val"Égalité stricte$1 == "admin"
$N ~ /regex/Correspond à une regex$1 ~ /^[A-Z]/
$N !~ /regex/Ne correspond pas$2 !~ /error/
/pattern/Correspond sur la ligne entière/ERROR/
&& ||ET / OU logiques$2 > 0 && $3 < 100

Ce dernier tableau regroupe les fonctions intégrées les plus utiles. Trois d'entre elles rendent awk autonome sur des traitements qu'on confie souvent à sed : gsub() remplace toutes les occurrences directement dans un champ, substr() extrait une portion de chaîne, et split() découpe une valeur en tableau, ce qui permet un second niveau de découpage à l'intérieur d'un champ déjà séparé.

ÉlémentRôleExemple
BEGIN { }Bloc exécuté avant la lectureBEGIN { print "Titre" }
END { }Bloc exécuté après la lectureEND { print total }
length()Longueur d'une chaînelength($1)
substr(s,i,n)Extrait une sous-chaînesubstr($1,1,3)
gsub(r,s)Remplace toutes les occurrencesgsub(/old/,"new")
split(s,a,fs)Découpe une chaîne en tableausplit($1,parts,"-")
tolower() / toupper()Change la cassetolower($1)
printAffiche (avec saut de ligne)print $1, $2
printfAffichage formaté, sans saut autoprintf "%-10s", $1
%s / %d / %.2fChaîne / entier / décimalprintf "%.2f", $3
arr[$1]++Compteur par clécount[$1]++
for (k in arr)Parcourt les clés d'un tableaufor (ip in count)
delete arr[k]Supprime une clédelete data["tmp"]

Vous maîtrisez awk lorsque vous pouvez cocher chacun de ces points :

  • Je sais extraire une colonne avec $N
  • Je sais définir un séparateur avec -F
  • Je sais filtrer les lignes avec une condition
  • Je sais utiliser NR, NF et $0
  • Je sais calculer une somme avec le bloc END
  • Je sais formater une sortie avec printf
  • Je sais utiliser les tableaux associatifs
  • Je sais filtrer avec une expression régulière (~)
  • Je sais structurer un traitement avec BEGIN et END
  • Je sais générer un rapport complet avec en-tête et total

La commande awk est un outil fondamental pour quiconque travaille avec des données textuelles. Grâce à son découpage automatique en champs, ses conditions flexibles et ses capacités de calcul, elle permet de traiter, analyser et transformer des fichiers structurés en quelques lignes. Que ce soit pour parser des logs, traiter des CSV ou générer des rapports, la maîtrise de awk vous fera gagner un temps considérable.

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce site vous est utile ?

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

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn