Aller au contenu principal

Transformer du texte : introduction à sed et awk

Notions théoriques

Quand grep et cut ne suffisent plus

grep cherche, cut extrait une colonne fixe. Mais dès qu'il faut modifier du texte, ou raisonner sur des colonnes mal alignées (espaces multiples, tabulations variables) et faire des calculs, deux outils plus puissants prennent le relais : sed (éditeur de flux) et awk (langage de traitement par colonnes).

sed : l'éditeur de flux

sed lit un texte ligne par ligne et applique une transformation, sans jamais ouvrir d'éditeur interactif.

sed 's/ancien/nouveau/' fichier.txt
  • s/ancien/nouveau/ : substitue la première occurrence d'ancien par nouveau, sur chaque ligne.
  • s/ancien/nouveau/g : le suffixe g (global) remplace toutes les occurrences de la ligne, pas seulement la première.
  • s/ancien/nouveau/I : le suffixe I ignore la casse.

Si le motif recherché contient lui-même un /, changez de séparateur pour éviter d'avoir à l'échapper :

sed 's|/var/log|/srv/log|' fichier.txt

Sélectionner des lignes par adresse :

sed '2d' fichier.txt # supprime la ligne 2
sed '/^#/d' fichier.txt # supprime les lignes commençant par # (les commentaires)
sed -n '/ERROR/p' fichier.txt # affiche seulement les lignes contenant ERROR
sed -n '1,10p' fichier.txt # affiche seulement les lignes 1 à 10

L'option -n coupe l'affichage automatique de chaque ligne : sans elle, sed -n '/ERROR/p' afficherait chaque ligne deux fois.

danger

sed -i modifie le fichier en place, directement, sans confirmation ni sauvegarde automatique. Testez toujours votre commande sed sans -i d'abord (la sortie s'affiche simplement à l'écran, le fichier reste intact), et une fois certain du résultat, utilisez sed -i.bak 's/.../.../g' fichier : le suffixe .bak crée une copie de sauvegarde avant modification.

awk : traiter par colonnes et par calcul

awk découpe chaque ligne en champs, automatiquement séparés par les espaces (y compris multiples) — là où cut échoue sur des colonnes mal alignées.

awk '{ print $1, $3 }' fichier.txt
  • $1, $2... désignent les champs de la ligne courante, $0 désigne la ligne entière.
  • NF (Number of Fields) contient le nombre de champs de la ligne courante.
  • NR (Number of Records) contient le numéro de la ligne courante.
  • -F':' change le séparateur de champs (utile pour /etc/passwd, séparé par :).
awk -F: '{ print $1 }' /etc/passwd

Structure motif { action } : awk peut filtrer avant d'agir, comme grep, mais avec des comparaisons de champs :

awk -F: '$3 >= 1000 { print $1 }' /etc/passwd

(affiche le nom des comptes dont l'UID, 3e champ, est supérieur ou égal à 1000 — les comptes "humains", par convention Linux)

BEGIN et END, calculs et mise en forme :

awk '{ somme += $5 } END { print "Total :", somme }' fichier.txt

awk '{ printf "%-15s %5d\n", $1, $2 }' fichier.txt

BEGIN { } s'exécute une seule fois avant de lire la première ligne, END { } une seule fois après la dernière — typiquement pour initialiser ou afficher un total. printf permet un alignement précis (%-15s = chaîne alignée à gauche sur 15 caractères, %5d = nombre aligné à droite sur 5 caractères), contrairement à print qui se contente de séparer les valeurs par des espaces.

Récapitulatif : quel outil pour quel besoin ?

BesoinOutil
Chercher une ligne contenant un motifgrep
Extraire une colonne à séparateur fixe et uniquecut
Remplacer du texte, supprimer des lignessed
Calculer, formater, filtrer par colonnes mal alignéesawk
attention

Ni sed ni awk ne sont adaptés pour analyser du JSON ou du HTML : ce sont des formats structurés que ces outils, pensés pour du texte ligne par ligne, interprètent mal dès que la structure devient complexe (guillemets imbriqués, accolades sur plusieurs lignes...). Pour du JSON, l'outil dédié est jq, hors du périmètre de ce cours.

Exemple pratique

# Lister les comptes "humains" (UID >= 1000) et leur dossier personnel
awk -F: '$3 >= 1000 { printf "%-15s %s\n", $1, $6 }' /etc/passwd

# Anonymiser les adresses IP d'un journal d'accès avant de le partager
sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/x.x.x.x/g' access.log > access_anonyme.log

Test de mémorisation/compréhension


Que fait l'option -i de sed, et pourquoi est-elle risquée ?


Que contient $0 dans un programme awk ?


Quelle est la différence entre NR et NF en awk ?


Quel bloc awk s'exécute après le traitement de la dernière ligne ?


TP pour réfléchir et résoudre des problèmes

Nous ajoutons à sauvegarde.sh un journal CSV de ses exécutions, exploité avec awk, et corrigeons sa configuration avec sed.

Étape 1 — Écrire une ligne CSV par sauvegarde


Bonne pratique - Toujours >> pour un journal

Utilisez >> (ajout en fin de fichier) et non > (écrasement) pour un fichier de journal : chaque exécution doit s'ajouter à l'historique, pas effacer les précédentes.

Étape 2 — Calculer le volume total avec awk


Bonne pratique - awk plutôt que cut pour un CSV à traiter

Dès qu'un traitement dépasse la simple extraction de colonne (ici, additionner des tailles), awk devient plus adapté que cut, qui ne sait qu'extraire.

Étape 3 — Filtrer les archives d'un jour donné


Bonne pratique - -v pour passer une variable shell à awk

awk fonctionne dans son propre monde de variables, séparé du shell. -v jour="$jour" est la façon propre de lui transmettre une valeur calculée par le script, plutôt que de bricoler une concaténation de chaînes.

Étape 4 — Corriger la configuration avec sed


Bonne pratique - Toujours un .bak avec sed -i

sed -i.bak plutôt que sed -i tout court : en cas d'erreur dans votre expression, vous conservez une copie du fichier original pour revenir en arrière immédiatement.

📌 Une solution