Commande awk : afficher des champs, le séparateur -F et les motifs conditionnels
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
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.txtalice pass 82
bob fail 47
carol pass 91
dave pass 68
erin fail 55Les 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.txtalice 82
bob 47
carol 91
dave 68
erin 55Si 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.txtalice82
bob47
carol91
dave68
erin55NR 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.txt1 3 82
2 3 47
3 3 91
4 3 68
5 3 55Le 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.
| Champ | Valeur de la première ligne | Signification |
|---|---|---|
| $1 | 192.0.2.10 | IP du client |
| $4 | [29/Oct/2026:00:01:12 | Date et heure de la requête |
| $6 | "GET | Méthode de la requête (précédée d'un guillemet double) |
| $7 | /index.html | URL de la requête |
| $9 | 200 | Code d'état |
| $10 | 5120 | Octets 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.log192.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 200Une 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 -315 x86_64)"
15 x86_64)"
15 x86_64)"2️⃣ Définir le séparateur avec awk -F
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.txtroot: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/nologinLe 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.txtroot /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
nobody /sbin/nologin
user /bin/bash
deploy /bin/bash
backup /sbin/nologinLes 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.csvitem 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.csvitem
"cable
keyboardPour 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.csvitem
"cable, usb"
keyboardPour 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.txtroot bash
bin nologin
daemon nologin
nobody nologin
user bash
deploy bash
backup nologin3️⃣ Motifs conditionnels de la commande awk
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.log203.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 404Les 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.log203.0.113.25 /wp-login.php
203.0.113.25 /wp-login.php
203.0.113.25 /.envPour 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.txtalice
carol
daveLa 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.txtnobody 65534
user 1000
deploy 1001
backup 1002Deux 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.txtuser /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.txtroot
user
deployawk -F: '$7 !~ /nologin/ {print $1, $7}' users.txtroot /bin/bash
user /bin/bash
deploy /bin/bashUne 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.csvkeyboard 2
mouse 5
monitor 1
keyboard 1
cable 10
mouse 2
monitor 2La 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.txtAvec 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.txt4️⃣ awk BEGIN, END, sommes et moyennes
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.
$ awk -F, 'NR > 1 {t += $3 * $4} END {printf "total %.2f\n", t}' sales.csvLa 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.log41298Si 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.csv2 90
3 189.5
4 378.5
5 423.5
6 468.5
7 508.3
8 886.3La 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.txt343 5 68.6BEGIN 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.csvitem total
keyboard 90
mouse 99.5
monitor 189
keyboard 45
cable 45
mouse 39.8
monitor 378Le 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.txtroot,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/nologinPour 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.csvkeyboard 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.00Contrairement à 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.csvkeyboard mouse monitor keyboard cable mouse monitor5️⃣ Analyse de journaux et options de la commande awk
🔲 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 -rn4 192.0.2.10
3 203.0.113.25
3 198.51.100.7
2 192.0.2.44L'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 | sort200 6
301 1
304 1
404 3
500 1En 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 500Pour 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.log404 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=awkLe 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 -rn31340 192.0.2.10
5120 192.0.2.44
4250 198.51.100.7
588 203.0.113.25Le 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
| Option | Rôle | Résultat dans cet article |
|---|---|---|
| -F fs | Dé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=val | Affecte une valeur à une variable avant l'exécution du programme | Passer 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 inplace | Enregistre la sortie dans le fichier d'origine au lieu de l'écran | Aprè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 |
| --version | Affiche les informations de version | La première ligne de [awk --version] indique GNU Awk 5 |
📎 Autres options : selon le manuel officiel
| Option | Rôle |
|---|---|
| -f program-file | Lit le programme AWK depuis un fichier au lieu du premier argument de la ligne de commande ; -f peut être indiqué plusieurs fois |
| -e program-text | Utilise 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 file | Semblable à -f, mais traitée en dernier et bloque les affectations de variables en ligne de commande ; pour les scripts #! |
| --traditional | Exécute en mode de compatibilité, sans reconnaître les extensions GNU |
| --posix | Active le mode de compatibilité et ajoute des restrictions, par exemple ne reconnaît pas func, synonyme de function |
| --lint | Avertit 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.
🔢 FAQ & contenus recommandés
Tri
Commande sort sous Linux : trier un fichier
La commande sort trie le contenu d'un fichier par ordre alphabétique ou numérique. Utilisez-la ensuite pour voir les totaux d'awk du plus grand au plus petit.
Suppression des doublons
Commande uniq sous Linux
La commande uniq réduit à une seule les lignes identiques consécutives et, avec -c, compte leurs répétitions.
Affichage de fichiers
Commandes head et tail sous Linux
Les commandes head et tail affichent uniquement les premières ou dernières lignes d'un fichier. Elles servent souvent à vérifier le journal d'accès d'un serveur.
ℹ️ 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.