← retour aux snippets

awk: extraire et agréger des colonnes

Extraire des champs, filtrer et agréger des lignes (compte, somme, moyenne) rapidement avec awk.


objectif

Manipuler des fichiers texte ou des sorties de commandes en extrayant des colonnes, filtrant des lignes et calculant des statistiques simples.

code minimal

# extraire la 1re colonne (séparateur: espaces/tabs) et compter les occurrences
awk '{print $1}' fichier.txt | sort | uniq -c | sort -nr | head -n 10

utilisation

# définir un séparateur de champs personnalisé (ex: CSV simple sans guillemets)
awk -F',' '{print $2}' data.csv

# ignorer les lignes vides et celles commençant par #
awk 'NF && $0 !~ /^#/' config.list

# filtrer selon une condition sur une colonne (ex: 9e colonne >= 400)
awk '$9 >= 400 {print $0}' access.log

# sélectionner des colonnes spécifiques et les réordonner (tabulation en sortie)
awk '{print $3 "\t" $1}' data.txt

# somme d'une colonne numérique (ex: total octets en 10e colonne)
awk '{sum += $10} END {print sum}' access.log

# moyenne et nombre de lignes valides (colonnes numériques)
awk '($2 ~ /^[0-9]+(\.[0-9]+)?$/) {c++; s+=$2} END {if(c) printf "moy=%.3f (n=%d)\n", s/c, c}' mesures.txt

# ajouter un en-tête aux résultats agrégés
awk '{c[$1]++} END {print "val\tcount"; for (k in c) print k "\t" c[k]}' fichier.txt | column -t

variante(s) utile(s)

# définir le séparateur d'entrée/sortie (FS/OFMT/OFS) et format numérique
awk 'BEGIN{FS="|"; OFS=","} {print $1, $3}' data.psv

# somme par groupe (clé = colonne 1), tri décroissant
awk '{sum[$1]+=$2} END {for(k in sum) printf "%s\t%d\n", k, sum[k]}' sales.tsv | sort -k2,2nr

# top N par groupe (clé = colonne 1, valeur = colonne 2)
awk '{c[$1][$2]++} END {for (k in c) {print "## " k; for (v in c[k]) print v, c[k][v]}}' data.txt

# filtrer par regex sur une colonne (ex: emails du domaine data.pm)
awk -F'[ \t]+' '$2 ~ /@example\.com$/ {print $0}' users.txt

# conserver l'ordre d'apparition (déduplication stable)
awk '!seen[$0]++' fichier.txt

# joindre deux fichiers sur une clé (colonne 1), enrichir (hash-map)
# build map depuis b.txt: clé=col1, val=col2; puis imprimer a.txt + val
awk 'NR==FNR {map[$1]=$2; next} {print $0, map[$1]}' b.txt a.txt

# calcul percentiles approximatifs (p50/p90/p99) via sort + awk
sort -n valeurs.txt | awk '{
  a[NR]=$1
} END {
  n=NR
  p50=a[int(0.5*n+0.5)]
  p90=a[int(0.9*n+0.5)]
  p99=a[int(0.99*n+0.5)]
  printf "p50=%s p90=%s p99=%s\n", p50, p90, p99
}'

notes

  • par défaut, FS (séparateur) = espaces/tabs; utilisez -F',' pour CSV simple, -F'|' pour PSV, etc.
  • pour CSV complexes avec guillemets/échappements, préférez csvtool, mlr (miller) ou un script Python.
  • utilisez LC_ALL=C pour accélérer les tris et comparaisons ASCII simples.
  • awk '!seen[$0]++' est une déduplication stable en mémoire; pour des fichiers énormes, passez par sort -u.
  • contrôlez la sortie avec OFS (séparateur de champs) et printf pour formater proprement.