Linux / Commande awk : extraire des champs, filtrer et calculer une somme
awk découpe son entrée en enregistrements et en champs pour sélectionner des valeurs, filtrer des lignes et effectuer des calculs. Par défaut, un enregistrement est une ligne et les champs sont séparés par des suites de blancs. Utilisez $0 pour la ligne entière, $1 pour le premier champ, NF pour le nombre de champs et NR pour le nombre d'enregistrements lus.
Awk convient aux extractions de colonnes, aux regroupements de journaux et aux petits rapports. Avant un calcul, vérifiez toutefois la structure et le format des valeurs : une donnée manquante ou non numérique ne doit pas être transformée silencieusement en résultat apparemment valide. Les exemples utilisent GNU awk dans Bash, sur des données fictives.
Syntaxe et préparation d'une entrée connue
awk [options] 'motif { action }' [fichiers…]
Chaque règle comporte une condition et une action. Sans condition, l'action s'applique à chaque enregistrement. Sans fichier, awk lit son entrée standard. Les guillemets simples autour du programme empêchent le shell de remplacer lui-même les expressions $1 et $2.
awk_lab=$(mktemp -d "$HOME/awk-lab.XXXXXX")
cd -- "$awk_lab"
printf 'name amount\nAna 12\nBob 7\nCara 11\n' > amounts.txt
Le fichier contient un en-tête connu suivi de trois noms et valeurs. Le répertoire d'exercice est neuf ; notez son chemin pour retrouver les fichiers et quittez-le ensuite avec cd "$HOME". Consultez man awk pour l'implémentation de votre système.
Observer les champs et les numéros de ligne
awk '{print NR, NF, $1, $2}' amounts.txt
1 2 name amount
2 2 Ana 12
3 2 Bob 7
4 2 Cara 11
Chaque enregistrement possède deux champs. NR inclut l'en-tête ; la première ligne de données a donc le numéro 2. $0 désigne l'enregistrement complet, tandis que $NF désigne son dernier champ.
Pour afficher seulement la deuxième colonne après l'en-tête :
awk 'NR > 1 {print $2}' amounts.txt
12
7
11
La séparation par défaut regroupe les blancs, contrairement à une sélection avec un espace littéral dans cut et ses champs. Un champ absent donne une chaîne vide lorsqu'il est utilisé comme texte ; dans une opération numérique, il peut contribuer comme zéro. Cette facilité justifie de valider les données avant de faire confiance à une somme.
Filtrer selon une valeur et passer un paramètre
Sur ce fichier dont les données sont connues, sélectionnez les noms associés à une valeur d'au moins 10 :
LC_ALL=C awk 'NR > 1 && $2 >= 10 {print $1}' amounts.txt
Ana
Cara
&& demande que les deux conditions soient vraies : la ligne n'est pas l'en-tête et le champ atteint le seuil. Pour rendre celui-ci paramétrable sans insérer du texte dans le programme awk, passez une variable avec -v :
LC_ALL=C awk -v threshold=11 'NR > 1 && $2 >= threshold {print $1, $2}' amounts.txt
La sortie est Ana 12, puis Cara 11. Pour passer une variable de shell, citez sa valeur, par exemple -v threshold="$seuil", et conservez le programme awk fixe. Le format des valeurs doit lui aussi être adapté au calcul prévu.
Calculer avec BEGIN et END
BEGIN s'exécute avant les enregistrements ; END s'exécute après leur traitement. Une variable peut donc accumuler les valeurs puis être affichée une seule fois :
LC_ALL=C awk 'BEGIN {sum = 0} NR > 1 {sum += $2} END {print sum}' amounts.txt
30
La somme est 12 + 7 + 11. Ce programme convient au jeu de données préparé, mais ne vérifie pas que chaque ligne contient deux champs ni que le second est un nombre. Il suppose aussi un en-tête unique. Avec plusieurs fichiers, NR continue d'augmenter ; un en-tête dans chaque fichier demande une règle adaptée, éventuellement fondée sur FNR, le compteur du fichier courant.
Refuser les valeurs invalides avant d'afficher un total
Enregistrez le programme suivant dans validate.awk. Le bloc complet crée ce fichier, puis l'exécute sur les données valides :
cat > validate.awk <<'AWK'
BEGIN {sum = 0; count = 0}
NR == 1 {next}
NF != 2 || $2 !~ /^[0-9]+([.][0-9]+)?$/ {
print "invalid row " NR ": " $0 > "/dev/stderr"
bad = 1
next
}
{sum += $2; count++}
END {
if (bad || count == 0) exit 1
print sum
}
AWK
LC_ALL=C awk -f validate.awk amounts.txt
Le résultat est encore 30, avec un statut 0. Le programme ignore la première ligne parce que cet exercice possède un en-tête connu. Il accepte ensuite exactement deux champs et un nombre décimal non négatif, avec des chiffres avant le point et, si un point est présent, après celui-ci. Il ne prend pas en charge les noms contenant des espaces.
Pour constater un refus sans modifier la bonne entrée, créez une copie avec une ligne incorrecte :
cp amounts.txt amounts-invalid.txt
printf 'Dana missing\n' >> amounts-invalid.txt
LC_ALL=C awk -f validate.awk amounts-invalid.txt
La commande signale sur la sortie d'erreur :
invalid row 5: Dana missing
Le statut attendu est 1 et aucun total n'est affiché. next saute l'addition pour la ligne invalide, et bad empêche ensuite de publier une somme partielle comme si elle était complète. L'absence de toute ligne de données provoque aussi un statut 1. Dans un script, contrôlez ce statut avant d'utiliser une sortie enregistrée.
Cette règle est volontairement précise : elle rejette les nombres négatifs, les exposants, les virgules décimales et les champs vides. Adaptez-la si ces formats sont autorisés, ainsi que le traitement de l'en-tête et des noms. Ne supprimez pas simplement la validation pour faire disparaître les erreurs.
Changer le séparateur sans supposer un parseur CSV
-F définit le séparateur de champs. Pour deux-points :
printf 'Ana:12\nBob:7\n' | awk -F ':' '{print $1, $2}'
Ana 12
Bob 7
La virgule entre les expressions de print utilise le séparateur de sortie, un espace par défaut. Le séparateur d'entrée et celui de sortie sont des réglages distincts.
Le mode awk -F ',' ne suffit pas à interpréter un CSV général : une virgule dans un champ entre guillemets n'est pas reconnue comme faisant partie de ce champ. Choisissez un analyseur CSV ou un mode explicitement prévu pour ce format. Une fonction propre à une version de GNU gawk ne doit pas être supposée présente dans toute commande nommée awk.
Enregistrer le résultat et retenir les repères
LC_ALL=C awk -f validate.awk amounts.txt > total.txt
cat total.txt
Le fichier contient 30. Choisissez une nouvelle destination et vérifiez le statut d'awk avant d'utiliser ce résultat dans un traitement réel. Ne redirigez pas vers le fichier d'entrée, qui peut être vidé par le shell avant sa lecture. Les données valides sont restées intactes ; vous pouvez corriger la copie incorrecte ou revenir à l'original pour reprendre l'essai.
| Repère | Signification |
|---|---|
$0, $1, $NF |
Enregistrement complet, premier champ et dernier champ. |
NF |
Nombre de champs de l'enregistrement courant. |
NR, FNR |
Nombre d'enregistrements lus globalement et dans le fichier courant. |
-F séparateur |
Définir la séparation des champs d'entrée. |
-v nom=valeur |
Initialiser une variable avant le traitement. |
-f programme.awk |
Lire les règles dans un fichier. |
BEGIN, END |
Exécuter une action avant ou après les enregistrements. |
Le guide officiel GNU explique les champs et les références $0, $1 et NF, ainsi que les options d'exécution de gawk. Vérifiez les extensions utilisées lorsque le script doit fonctionner avec d'autres implémentations.




