Apprenez en lisant dans l'ordre

awk — Agrégation et rapports

Pratique awk : l'ordre d'exécution de BEGIN { } et END { }, s += $1 pour cumuler la colonne 1 en un total, et le comptage avec NR ou { c++ } pour construire des rapports d'agrégation — illustré et en pratique dans un terminal en navigateur.

Exécuter avant et après — BEGIN et END

awk traite chaque ligne l'une après l'autre, mais tu peux placer le travail à exécuter une seule fois avant et après dans BEGIN { ... } et END { ... }. BEGIN s'exécute une fois avant la lecture de la première ligne, et END s'exécute une fois après que toutes les lignes ont été lues. Utilise-les pour afficher un en-tête au départ ou pour afficher un résumé à la toute fin.

L'ordre d'exécution de BEGIN et END
BEGIN { ... }une fois avantla lectureafficher unen-tête d'abord{ body }répété par ligneune ligneà la foisEND { ... }une fois aprèstoutes les lignesafficher sommeou compte
BEGIN s'exécute une fois avant le traitement, le corps une fois par ligne, et END une fois après.
FormeSignification
BEGIN { ... }Exécuté une fois avant la lecture de la première ligne
{ ... }Le corps exécuté de façon répétée, une ligne à la fois
END { ... }Exécuté une fois après la lecture de toutes les lignes
s += $1Accumule la colonne 1 dans la variable s (un total cumulé)
NRNombre de lignes lues jusqu'ici (le nombre total de lignes à la fin)
{ c++ } END { print c }Incrémente c par ligne et affiche le compte à la fin
printf 'start\nmiddle\nend\n' > lines.txt          # créer 3 lignes de données
awk 'BEGIN { print "--- report ---" } { print $0 } END { print "rows:", NR }' lines.txt
# un en-tête au départ, rows: 3 à la fin

① Crée un fichier de données à 3 lignes avec printf 'apple\nbanana\ncherry\n' > fruits.txt.

② Vérifie le contenu avec cat fruits.txt.

③ Avec awk, affiche une ligne d'en-tête une fois dans BEGIN, affiche chaque ligne telle quelle dans le corps, et affiche le nombre total de lignes une fois dans END en utilisant NR.

④ Vérifie qu'un en-tête est en haut, les 3 lignes au milieu, et le nombre de lignes à la fin. (Si tu l'exécutes correctement, une explication apparaîtra.)

Linux console
0 / 3 exécutée(s)
Loading Linux Terminal...

Somme et compte — s += $1 et NR

Avec awk tu peux utiliser des variables sans les déclarer, et les nombres s'additionnent directement. En écrivant { s += $1 } dans le corps, la première colonne de chaque ligne est accumulée dans la variable s, et END { print s } affiche le total à la fin. Pour un compte, soit tu affiches NR (le nombre de lignes lues) directement dans END, soit tu incrémentes un compteur avec { c++ } et tu l'affiches avec END { print c }. Tu peux ainsi construire des rapports d'agrégation comme un total de ventes ou un nombre d'enregistrements.

Accumuler la colonne 1 en un total
10 apple20 banana30 cherrys += $1 -> s=10s += $1 -> s=30END print s -> 60
s += $1 ajoute la colonne 1 ligne par ligne, et END affiche le total de 60.
printf '120 mon\n80 tue\n200 wed\n' > sales.txt   # créer 3 lignes avec des nombres
awk '{ s += $1 } END { print "total:", s }' sales.txt   # total: 400
awk 'END { print "days:", NR }' sales.txt               # days: 3

① Crée 3 lignes avec des nombres en utilisant printf '50 a\n70 b\n30 c\n' > nums.txt.

② Vérifie le contenu avec cat nums.txt.

③ Dans le corps awk, accumule la colonne 1 dans une variable, et affiche son total une fois dans END.

④ Ensuite, dans END de awk, utilise NR pour afficher le nombre de lignes (le nombre d'enregistrements).

⑤ Vérifie que le total et le compte s'affichent à l'écran.

Linux console
0 / 4 exécutée(s)
Loading Linux Terminal...

Compter avec un compteur — { c++ } END { print c }

NR compte toutes les lignes, mais quand tu veux compter uniquement les lignes qui correspondent à une condition, utilise un compteur dans le corps. { c++ } incrémente la variable c de 1 pour chaque ligne lue, et END { print c } affiche ce compte. En ajoutant un motif comme /pat/{ c++ }, tu comptes uniquement les lignes contenant une chaîne particulière.

Compter uniquement les lignes correspondantes avec un compteur
pass xfail ypass z/pass/ c++ -> c=1fail -> non comptéEND print c -> 2
/pass/{ c++ } incrémente c uniquement sur les lignes correspondantes, et END affiche le compte de 2.
FormeSignification
{ c++ }Incrémente la variable c de 1 pour chaque ligne lue
/pattern/{ c++ }Incrémente c uniquement sur les lignes contenant pattern
END { print c }Affiche le compte c une fois à la fin
printf 'ok pay\nng pay\nok ship\n' > log.txt        # créer 3 lignes avec un statut
awk '/ok/{ c++ } END { print "ok count:", c }' log.txt   # compter les lignes contenant ok -> 2

① Crée 3 lignes avec un statut en utilisant printf 'pass x\nfail y\npass z\n' > result.txt.

② Vérifie le contenu avec cat result.txt.

③ Avec awk, incrémente un compteur uniquement sur les lignes contenant pass, et affiche ce compte une fois dans END.

④ Vérifie que le compte affiché correspond au nombre de lignes contenant pass.

⑤ Sur le même result.txt, exécute à la fois awk 'END { print NR }' result.txt (total des lignes) et awk '/pass/{ c++ } END { print "pass count:", c }' result.txt (compte des lignes correspondantes) et compare la différence.

Linux console
0 / 4 exécutée(s)
Loading Linux Terminal...
QUIZ

Vérification des connaissances

Répondez à chaque question une par une.

Question 1Quand le corps de BEGIN { ... } s'exécute-t-il ?

Question 2Que montre awk '{ s += $1 } END { print s }' f ?

Question 3Que s'affiche-t-il quand tu affiches NR dans le bloc END ?