Commande awk : afficher des champs, le séparateur -F et les motifs conditionnels

Environnement de testFamille RHELAlmaLinux 9.8Compte rootVérifié le 2026-10-29

La commande awk est un outil Linux qui lit un fichier texte ligne par ligne, découpe chaque ligne en champs selon les espaces ou le séparateur que vous indiquez, et ne retient que les champs des lignes répondant à une condition pour les afficher ou faire des calculs. Sur un serveur AlmaLinux 9, nous avons compté les requêtes par IP et les occurrences par code d'état d'un fichier d'exemple de journal d'accès de serveur web avec une seule ligne reliée à sort par un pipe : les trois réponses 404 des douze lignes étaient toutes des requêtes vers wp-login.php et .env venant d'une seule IP.

La sortie ci-dessous a été obtenue avec le compte root dans un dossier de travail sur un serveur AlmaLinux 9.8. Le journal d'accès, la liste de comptes, les relevés de ventes et le fichier de scores sont des fichiers d'exemple créés pour le test, et les adresses IP et noms de compte qu'ils contiennent sont aussi des valeurs d'exemple.

1️⃣ Utilisation de base de la commande awk

  • ↪️ Numéros de champ et print

awk découpe chaque ligne lue selon les espaces et numérote les champs depuis le début : $1, $2, $3. Nous l'avons vérifié avec scores.txt, où le nom, le résultat et le score sont séparés par des espaces.

cat scores.txt
alice   pass  82
bob     fail  47
carol   pass  91
dave    pass  68
erin    fail  55

Les accolades entre apostrophes contiennent l'action à exécuter sur chaque ligne, et si vous listez après print des numéros de champ séparés par des virgules, seuls ces champs sortent. En affichant le premier et le troisième champ, il ne reste que le nom et le score.

awk '{print $1, $3}' scores.txt
alice 82
bob 47
carol 91
dave 68
erin 55

Si vous retirez la virgule entre les champs et écrivez $1 $3, les deux valeurs se suivent sans espace. La virgule de print insère le séparateur de sortie (un espace par défaut), et les valeurs écrites côte à côte sans virgule sont collées en une seule chaîne.

awk '{print $1 $3}' scores.txt
alice82
bob47
carol91
dave68
erin55

NR est le numéro de la ligne lue jusqu'ici, et NF le nombre de champs de cette ligne. $NF désigne le dernier champ, vous pouvez donc choisir la dernière colonne même si le nombre de champs varie d'une ligne à l'autre.

awk '{print NR, NF, $NF}' scores.txt
1 3 82
2 3 47
3 3 91
4 3 68
5 3 55

Le journal d'accès d'un serveur web est lui aussi séparé par des espaces, les champs se choisissent donc de la même façon. Voici les numéros de champ de la première ligne du journal de test.

ChampValeur de la première ligneSignification
$1192.0.2.10IP du client
$4[29/Oct/2026:00:01:12Date et heure de la requête
$6"GETMéthode de la requête (précédée d'un guillemet double)
$7/index.htmlURL de la requête
$9200Code d'état
$105120Octets envoyés
$11"-"Page précédente (Referer)
$12~$15"Mozilla/5.0 (X11; Linux x86_64)"User-agent (coupé à chaque espace)

Nous avons affiché $1, $7 et $9, qui correspondent à l'IP du client, à l'URL de la requête et au code d'état.

awk '{print $1, $7, $9}' access.log
192.0.2.10 /index.html 200
198.51.100.7 /about.html 200
192.0.2.10 /images/logo.png 200
203.0.113.25 /wp-login.php 404
203.0.113.25 /wp-login.php 404
192.0.2.10 /contact.html 200
198.51.100.7 /old-page.html 301
203.0.113.25 /.env 404
192.0.2.44 /index.html 200
198.51.100.7 /api/search?q=awk 500
192.0.2.44 /images/logo.png 304
192.0.2.10 /index.html 200

Une colonne dont la valeur contient des espaces, comme le user-agent, est coupée en plusieurs champs. NF valait 15 sur les trois premières lignes, et $NF est le dernier morceau du user-agent.

awk '{print NF, $NF}' access.log | head -3
15 x86_64)"
15 x86_64)"
15 x86_64)"

2️⃣ Définir le séparateur avec awk -F

  • ↪️ Séparateurs deux-points, virgule et expression régulière

Pour un fichier dont les colonnes sont séparées par un autre signe que l'espace, écrivez ce signe après -F. En affichant $1 sans -F dans la liste de comptes users.txt, créée sur le modèle de /etc/passwd, la plupart des lignes sont sorties entières.

awk '{print $1}' users.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
nobody:x:65534:65534:Kernel
user:x:1000:1000:Example
deploy:x:1001:1001:Deploy
backup:x:1002:1002::/home/backup:/sbin/nologin

Le séparateur par défaut est l'espace, donc une ligne reliée uniquement par des deux-points n'a qu'un seul champ. Seules les lignes nobody, user et deploy, qui ont un espace dans la colonne de description, sont coupées à cet espace.

Avec -F:, le deux-points devient le séparateur, et le nom de compte ($1) et le shell de connexion ($7) sont séparés.

awk -F: '{print $1, $7}' users.txt
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
nobody /sbin/nologin
user /bin/bash
deploy /bin/bash
backup /sbin/nologin

Les fichiers CSV séparés par des virgules se découpent avec -F,. En affichant l'article et la quantité des ventes de sales.csv, l'en-tête de la première ligne (item qty) est découpé de la même façon et apparaît aussi.

awk -F, '{print $2, $3}' sales.csv
item qty
keyboard 2
mouse 5
monitor 1
keyboard 1
cable 10
mouse 2
monitor 2

-F, ne convient pas aux CSV ayant des virgules dans des colonnes entre guillemets doubles. Dans quoted.csv, qui a des virgules dans la colonne des articles, les champs sont aussi coupés aux virgules entre guillemets, et seul le début du nom de l'article reste dans le deuxième champ.

awk -F, '{print $2}' quoted.csv
item
"cable
keyboard

Pour ces fichiers, le manuel officiel de GNU Awk présente la variable FPAT. Si vous écrivez la forme d'un champ en expression régulière au lieu d'un séparateur, une colonne entre guillemets sort comme un seul champ.

awk -v FPAT='([^,]*)|("[^"]*")' '{print $2}' quoted.csv
item
"cable, usb"
keyboard

Pour utiliser plusieurs séparateurs, écrivez-les en expression régulière entre crochets. Avec le deux-points et la barre oblique comme séparateurs, $NF devient le dernier nom du chemin du shell de connexion (bash, nologin).

awk -F'[:/]' '{print $1, $NF}' users.txt
root bash
bin nologin
daemon nologin
nobody nologin
user bash
deploy bash
backup nologin

3️⃣ Motifs conditionnels de la commande awk

  • ↪️ Expressions régulières, comparaisons et NR

Même en choisissant des champs, toutes les lignes sont affichées. Pour ne garder que celles qu'il vous faut, placez une condition (motif) avant les accolades. Une chaîne entre barres obliques sélectionne uniquement les lignes qui la contiennent, et si vous omettez l'action, la ligne entière est affichée.

awk '/wp-login/' access.log
203.0.113.25 - - [29/Oct/2026:00:04:51 +0000] "POST /wp-login.php HTTP/1.1" 404 196 "-" "Mozilla/5.0 (X11; Linux x86_64)"
203.0.113.25 - - [29/Oct/2026:00:04:52 +0000] "POST /wp-login.php HTTP/1.1" 404 196 "-" "Mozilla/5.0 (X11; Linux x86_64)"

Les lignes sélectionnées sont les mêmes qu'avec la commande grep, et awk peut directement choisir les champs de ces lignes et les afficher. En passant à awk par un pipe les deux mêmes lignes sélectionnées avec grep, il ne reste que l'IP et le code d'état.

grep wp-login access.log | awk '{print $1, $9}'
203.0.113.25 404
203.0.113.25 404

Les valeurs de champ se comparent avec ==, !=, >, >=, <, <=. Nous avons sélectionné uniquement les lignes dont le code d'état ($9) est 404, et affiché l'IP et l'URL de la requête.

awk '$9 == 404 {print $1, $7}' access.log
203.0.113.25 /wp-login.php
203.0.113.25 /wp-login.php
203.0.113.25 /.env

Pour comparer avec une chaîne, placez la valeur entre guillemets doubles. Nous avons sélectionné uniquement les noms dont le deuxième champ est pass.

awk '$2 == "pass" {print $1}' scores.txt
alice
carol
dave

La comparaison numérique sert à sélectionner par plage, comme avec les numéros de compte (UID). En sélectionnant les comptes dont l'UID vaut 1000 ou plus, on obtient les comptes standard ainsi que nobody, dont l'UID est 65534.

awk -F: '$3 >= 1000 {print $1, $3}' users.txt
nobody 65534
user 1000
deploy 1001
backup 1002

Deux conditions se combinent avec &&. En ajoutant la condition inférieure à 65534, nobody disparaît et il ne reste que les trois comptes standard et leurs dossiers personnels.

awk -F: '$3 >= 1000 && $3 < 65534 {print $1, $6}' users.txt
user /home/user
deploy /home/deploy
backup /home/backup

[~] vérifie si un champ correspond à une expression régulière, et [!~] s'il n'y correspond pas. En sélectionnant les comptes dont le shell de connexion ($7) se termine par bash, puis ceux dont le shell n'est pas nologin, on obtient les trois mêmes comptes.

awk -F: '$7 ~ /bash$/ {print $1}' users.txt
root
user
deploy
awk -F: '$7 !~ /nologin/ {print $1, $7}' users.txt
root /bin/bash
user /bin/bash
deploy /bin/bash

Une condition NR sélectionne par numéro de ligne. NR > 1 retire la ligne d'en-tête du CSV et ne laisse que les ventes.

awk -F, 'NR > 1 {print $2, $3}' sales.csv
keyboard 2
mouse 5
monitor 1
keyboard 1
cable 10
mouse 2
monitor 2

La sortie d'autres commandes se découpe de la même façon via un pipe. En choisissant la taille ($5) et le nom ($9) dans la sortie de ls -l, la première ligne est sortie vide, car la première ligne de ls -l, [total 24], n'a ni cinquième ni neuvième champ.

ls -l | awk '{print $5, $9}'

1567 access.log
79 quoted.csv
207 sales.csv
85 scores-copy.txt
85 scores.txt
315 users.txt

Avec NR > 1, la première ligne disparaît et il ne reste que les tailles et les noms de fichier.

ls -l | awk 'NR > 1 {print $5, $9}'
1567 access.log
79 quoted.csv
207 sales.csv
85 scores-copy.txt
85 scores.txt
315 users.txt

4️⃣ awk BEGIN, END, sommes et moyennes

  • ↪️ Variables et formats de sortie printf

Un bloc BEGIN s'exécute une fois avant la lecture de la première ligne, et un bloc END une fois après le traitement de la dernière. Pour une somme, ajoutez à une variable à chaque ligne et affichez-la dans END. Le schéma ci-dessous montre l'ordre que suit awk à chaque ligne pour totaliser les montants des ventes.

🔁 Ordre dans lequel awk traite sales.csv ligne par ligne
Schéma explicatif
🔁 Ordre de traitement
$ awk -F, 'NR > 1 {t += $3 * $4} END {printf "total %.2f\n", t}' sales.csv
① Ligne lueNR = 1date,item,qty,priceNR = 22026-10-01,keyboard,2,45.00NR = 32026-10-01,mouse,5,19.90NR = 82026-10-04,monitor,2,189.00Plus de ligne à lireLa ligne 8 est la dernière.
② Découpage des champs (-F,)$1date$2item$3qty$4priceLa ligne d'en-tête est découpée de la même façon.$12026-10-01$2keyboard$32$445.00$3 quantité, $4 prix unitaire$12026-10-01$2mouse$35$419.90$3 quantité, $4 prix unitaire$12026-10-04$2monitor$32$4189.00$3 quantité, $4 prix unitaireAucune ligne à découperLe bloc END ne lit aucune ligne.
③ Motif et actionNR > 1 fauxL'action est ignorée.t = (vide)NR > 1 vrait += 2 * 45.00t = 90NR > 1 vrait += 5 * 19.90t = 189.5NR > 1 vrait += 2 * 189.00t = 886.3Exécution de ENDtotal 886.30printf affiche t avec deux décimales.
La première ligne est l'en-tête, donc NR > 1 est faux et awk passe à la ligne suivante sans exécuter l'action.
À partir de la deuxième ligne, le motif est vrai, et 90, la quantité multipliée par le prix unitaire, s'ajoute à la variable t.
La variable t conserve sa valeur d'une ligne à l'autre, donc le total jusqu'à la troisième ligne est 189.5.
Les lignes 4 à 7 suivent le même ordre, et jusqu'à la dernière, la ligne 8, t atteint 886.3.
Après le traitement de la dernière ligne, le bloc END s'exécute une fois et printf affiche total 886.30.

La somme de tous les octets envoyés ($10) du journal d'accès était de 41298 octets. Une variable utilisée pour la première fois commence vide (0 en tant que nombre), il est donc inutile de la mettre à 0.

awk '{sum += $10} END {print sum}' access.log
41298

Si vous affichez la somme dans l'action exécutée à chaque ligne et non dans END, chaque ligne montre le total cumulé jusque-là. En affichant le numéro de ligne et t à chaque ajout de la quantité multipliée par le prix, on obtient sept lignes sans l'en-tête, et le 886.3 de la dernière ligne est le total général.

awk -F, 'NR > 1 {t += $3 * $4; print NR, t}' sales.csv
2 90
3 189.5
4 378.5
5 423.5
6 468.5
7 508.3
8 886.3

La moyenne se calcule dans END en divisant la somme par le nombre de lignes. La somme des cinq scores était 343 et la moyenne 68.6.

awk '{total += $3; n++} END {print total, n, total / n}' scores.txt
343 5 68.6

BEGIN sert à afficher une fois une ligne d'en-tête au-dessus des résultats. La ligne item total n'apparaît qu'une fois au-dessus des articles et des montants (quantité × prix unitaire).

awk -F, 'BEGIN {print "item", "total"} NR > 1 {print $2, $3 * $4}' sales.csv
item total
keyboard 90
mouse 99.5
monitor 189
keyboard 45
cable 45
mouse 39.8
monitor 378

Le séparateur de sortie se change avec la variable OFS dans BEGIN. Si OFS vaut une virgule, une virgule remplace l'espace à l'endroit des virgules de print, et la liste de comptes sort au format CSV.

awk 'BEGIN {FS = ":"; OFS = ","} {print $1, $3, $7}' users.txt
root,0,/bin/bash
bin,1,/sbin/nologin
daemon,2,/sbin/nologin
nobody,65534,/sbin/nologin
user,1000,/bin/bash
deploy,1001,/bin/bash
backup,1002,/sbin/nologin

Pour aligner les colonnes, utilisez printf. %-10s est une chaîne alignée à gauche sur 10 caractères, %3d un entier sur 3 caractères et %8.2f un nombre sur 8 caractères avec deux décimales.

awk -F, 'NR > 1 {printf "%-10s %8.2f\n", $2, $3, $3 * $4}' sales.csv
keyboard     2    90.00
mouse        5    99.50
monitor      1   189.00
keyboard     1    45.00
cable       10    45.00
mouse        2    39.80
monitor      2   378.00

Contrairement à print, printf ne passe pas à la ligne, ajoutez donc [\n] à la fin du format. Sans [\n], les noms d'articles se suivent sur une seule ligne.

awk -F, 'NR > 1 {printf "%s ", $2}' sales.csv
keyboard mouse monitor keyboard cable mouse monitor

5️⃣ Analyse de journaux et options de la commande awk

  • ↪️ Comptage des IP et des codes d'état, résumé des options

🔲 Analyse de journaux

Ajouter à une seule variable ne donne qu'un seul total. Pour compter par IP ou par code d'état, rassemblez les valeurs dans un tableau. n[$1]++ ajoute 1 à la case du tableau dont la clé est l'IP, et le for (ip in n) de END sort les cases une à une.

awk '{n[$1]++} END {for (ip in n) print n[ip], ip}' access.log | sort -rn
4 192.0.2.10
3 203.0.113.25
3 198.51.100.7
2 192.0.2.44

L'ordre de sortie de for (ip in n) n'est pas défini (selon le manuel de GNU Awk), nous avons donc trié par nombre de requêtes avec sort -rn. 192.0.2.10 arrive en tête avec 4 requêtes.

Les occurrences par code d'état se comptent de la même façon. Il y avait 3 codes 404 et 1 code 500.

awk '{n[$9]++} END {for (s in n) print s, n[s]}' access.log | sort
200 6
301 1
304 1
404 3
500 1

En extrayant uniquement les codes d'état et en les passant à sort et uniq -c, on obtient les mêmes nombres.

awk '{print $9}' access.log | sort | uniq -c
      6 200
      1 301
      1 304
      3 404
      1 500

Pour ne voir que les réponses d'erreur, placez une condition sur le code d'état. Les lignes à partir de 400 étaient trois requêtes cherchant wp-login.php et .env, et une erreur 500.

awk '$9 >= 400 {print $9, $1, $7}' access.log
404 203.0.113.25 /wp-login.php
404 203.0.113.25 /wp-login.php
404 203.0.113.25 /.env
500 198.51.100.7 /api/search?q=awk

Le total d'octets envoyés par IP se calcule aussi en ajoutant dans un tableau. 192.0.2.10 a le plus reçu, avec 31340 octets.

awk '{b[$1] += $10} END {for (ip in b) print b[ip], ip}' access.log | sort -rn
31340 192.0.2.10
5120 192.0.2.44
4250 198.51.100.7
588 203.0.113.25

Le champ de l'heure ($4) se compare comme une chaîne. Entre lignes de même date et de même format, l'ordre des chaînes suit l'ordre des heures, nous avons donc sélectionné uniquement les quatre requêtes de 00:05 à juste avant 00:10.

awk '$4 >= "[29/Oct/2026:00:05" && $4 < "[29/Oct/2026:00:10" {print $4, $7}' access.log
[29/Oct/2026:00:05:30 /contact.html
[29/Oct/2026:00:07:02 /old-page.html
[29/Oct/2026:00:07:15 /.env
[29/Oct/2026:00:09:48 /index.html

🔲 Options de la commande awk

📌 Options principales : résultats de cet article

OptionRôleRésultat dans cet article
-F fsDéfinit le séparateur des champs d'entrée-F: sépare le nom de compte ($1) et le shell de connexion ($7) de users.txt ; -F, affiche l'article et la quantité de sales.csv avec l'en-tête (item qty)
-v var=valAffecte une valeur à une variable avant l'exécution du programmePasser la variable shell min avec -v min=$min affiche six lignes d'au moins 1000 octets envoyés ; avec -v FPAT=…, une colonne entre guillemets de quoted.csv sort comme un seul champ
-i inplaceEnregistre la sortie dans le fichier d'origine au lieu de l'écranAprès gawk -i inplace, rien n'apparaît à l'écran et la copie de scores.txt passe à deux colonnes, nom et score ; avec -v inplace::suffix=.bak, le contenu précédent reste dans un fichier .bak
--versionAffiche les informations de versionLa première ligne de [awk --version] indique GNU Awk 5

📎 Autres options : selon le manuel officiel

OptionRôle
-f program-fileLit le programme AWK depuis un fichier au lieu du premier argument de la ligne de commande ; -f peut être indiqué plusieurs fois
-e program-textUtilise le texte de la ligne de commande comme source du programme AWK ; s'emploie avec des fonctions de bibliothèque chargées par -f ou --include
-E fileSemblable à -f, mais traitée en dernier et bloque les affectations de variables en ligne de commande ; pour les scripts #!
--traditionalExécute en mode de compatibilité, sans reconnaître les extensions GNU
--posixActive le mode de compatibilité et ajoute des restrictions, par exemple ne reconnaît pas func, synonyme de function
--lintAvertit des constructions douteuses ou difficiles à porter vers d'autres implémentations d'AWK ; avec --lint=fatal, les avertissements deviennent des erreurs fatales
--dump-variablesÉcrit dans un fichier la liste triée des variables globales avec leur type et leur valeur finale ; awkvars.out si aucun fichier n'est indiqué

🔲 Simulateur de la commande awk

Dans le simulateur ci-dessous, vous pouvez saisir vous-même des commandes awk sur les mêmes fichiers de test.

Simulateur de la commande awkGNU Awk 5
[root@server work]#
Un petit interpréteur awk qui fonctionne uniquement dans votre navigateur. Les quatre fichiers de test sont ceux utilisés pour les mesures, et ↑↓ rappelle les commandes précédentes.

🔢 FAQ & contenus recommandés

Le shell ne remplace pas $min entre apostrophes, qui arrive tel quel à awk : passez-le donc avec l'option -v. Si vous mettez 1000 dans la variable shell min et passez -v min=$min, les six lignes d'au moins 1000 octets envoyés s'affichent. Si vous entourez le programme awk de guillemets doubles, le shell remplace d'abord même le $1 de [print $1] par une valeur vide, et la ligne entière est affichée.

Avec -i inplace, GNU Awk enregistre la sortie dans le fichier d'origine au lieu de l'écran. En exécutant avec gawk -i inplace un programme affichant le premier et le troisième champ sur une copie de scores.txt, rien n'est apparu à l'écran et le fichier est passé à deux colonnes, nom et score. Comme le fichier d'origine est écrasé directement, ajoutez -v inplace::suffix=.bak pour garder le contenu précédent dans un fichier .bak.

Sur le serveur AlmaLinux 9, /usr/bin/awk était un lien symbolique vers gawk, et la première ligne de [awk --version] indiquait GNU Awk 5. Sur ce serveur, les deux noms exécutent le même programme. Avant d'utiliser des fonctions de GNU Awk comme -i inplace ou FPAT, vérifiez avec [awk --version] qu'il s'agit bien de GNU Awk.

ℹ️ Mention d'affiliation
Le contenu de ce site contient des liens d'affiliation. Lorsqu'un visiteur achète un produit ou un service via l'un de ces liens, le site perçoit une commission du vendeur. Le montant payé par l'acheteur(il baisse lors des promotions ↓), lui, n'augmente pas. Les prix, remises et stocks indiqués correspondent à la date de rédaction et peuvent différer ; vérifiez-les donc auprès du vendeur avant d'acheter. Les produits sont choisis et évalués selon nos propres critères, et les commissions n'influencent ni l'ordre de présentation ni le contenu des évaluations.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Prouvez que vous êtes humain : 1   +   1   =