Aller au contenu
Administration Linux medium

Transformer des fichiers avec sed

10 min de lecture

sed est l’outil qu’on utilise quand on ne veut pas ouvrir un éditeur. Vous avez 50 fichiers de configuration à mettre à jour, un mot de passe à masquer, un hostname à changer de prod à staging sur tous les fichiers d’un dossier — sed fait ça en une ligne, de façon scriptable et répétable.

C’est un outil direct LFCS (“Compare and Manipulate File Content”) et RHCSA (“Create and Edit Text Files”, “Use regular expressions to find, replace, and delete strings”).

  • Substituer du texte avec la commande s/avant/après/ et ses variantes
  • Modifier un fichier directement sur disque avec sed -i sans perdre l’original
  • Cibler des lignes précises avec des adresses numériques ou des patterns regex
  • Supprimer des lignes, des commentaires et des lignes vides
  • Enchaîner plusieurs transformations en une seule commande avec -e
  • Réorganiser des champs avec des groupes de capture \1, \2
  • Appliquer un workflow complet de migration de fichier de config

sed est l’outil par défaut dès que vous devez transformer du texte de façon automatisable et non interactive :

  • changer l’URL d’une base de données dans db.conf lors d’une migration prod → staging
  • masquer un mot de passe ou une clé API dans des fichiers de config avant de les versionner
  • supprimer les commentaires et lignes vides d’un fichier de configuration pour le passer à un parser
  • normaliser les espaces autour des = dans des dizaines de fichiers .ini ou .conf
  • extraire uniquement les lignes d’erreur d’un log pour alimenter un rapport

Dans un script de déploiement ou un playbook Ansible, sed -i est souvent la première solution — simple, sans dépendance, disponible sur tout système Linux.

La commande s est le coeur de sed. Sa syntaxe :

s/PATTERN/REMPLACEMENT/FLAGS
  • PATTERN : expression régulière (BRE par défaut, ERE avec -E)
  • REMPLACEMENT : le texte de remplacement
  • FLAGS : g (global), i (insensible à la casse), 2 (deuxième occurrence seulement)

Substitution basique — première occurrence par ligne

Section intitulée « Substitution basique — première occurrence par ligne »
Fenêtre de terminal
sed 's/prod/staging/' hosts.old
192.168.1.10 web01.staging.example.com web01
192.168.1.11 web02.staging.example.com web02
192.168.1.20 db01.staging.example.com db01
10.0.0.5 bastion.staging.example.com bastion

Sans flag, sed remplace seulement la première occurrence sur chaque ligne.

Fenêtre de terminal
echo "prod prod prod" | sed 's/prod/staging/g'
staging staging staging

Sans -i, sed envoie le résultat sur la sortie standard — le fichier original est intact. Avec -i, la modification est écrite directement dans le fichier.

Fenêtre de terminal
cp hosts.old hosts.staging
sed -i 's/prod/staging/g' hosts.staging

L’extension passée après -i devient le suffixe du fichier de sauvegarde :

Fenêtre de terminal
sed -i.bak 's/prod/staging/g' hosts.staging
Fenêtre de terminal
ls -1
# hosts.staging ← fichier modifié
# hosts.staging.bak ← copie de l'original

Par défaut, sed applique la commande à toutes les lignes. Une adresse limite l’action à une sélection.

Fenêtre de terminal
# Modifier seulement la ligne 2
sed '2s/example/EXAMPLE/' hosts.old
# Modifier les lignes 1 à 2
sed '1,2s/example/EXAMPLE/' hosts.old
# Modifier la dernière ligne
sed '$s/example/EXAMPLE/' hosts.old
Fenêtre de terminal
# Modifier seulement les lignes qui contiennent "web"
sed '/web/s/prod/staging/' hosts.old
192.168.1.10 web01.staging.example.com web01
192.168.1.11 web02.staging.example.com web02
192.168.1.20 db01.prod.example.com db01
10.0.0.5 bastion.prod.example.com bastion

Les lignes db01 et bastion ne correspondent pas — elles ne sont pas modifiées.

La commande d supprime les lignes sélectionnées de la sortie.

Fenêtre de terminal
# Supprimer les commentaires et les lignes vides d'un fichier de config
sed '/^#/d; /^$/d' db.conf
host = db.internal.example.com
port = 5432
user=admin
password= secret123
database=production
max_connections = 100
connect_timeout= 30

Les commentaires (# ...) et les lignes vides ont été supprimés. Le fichier original est intact — utilisez -i pour écrire le résultat.

Plutôt que d’exécuter sed plusieurs fois, enchaînez avec -e :

Fenêtre de terminal
sed -E \
-e '/^#/d' \
-e '/^$/d' \
-e 's/[[:space:]]*=[[:space:]]*/=/' \
db.conf
host=db.internal.example.com
port=5432
user=admin
password=secret123
database=production
max_connections=100
connect_timeout=30

Trois transformations appliquées en une passe :

  1. Suppression des commentaires
  2. Suppression des lignes vides
  3. Normalisation des espaces autour de =

Avec -E, les parenthèses (...) créent des groupes. \1, \2 réinjectent le contenu capturé dans le remplacement.

Fenêtre de terminal
# Inverser IP et hostname dans hosts.old
sed -E 's/^([0-9.]+)([[:space:]]+)([a-z0-9.]+)/\3\2\1/' hosts.old
web01.prod.example.com 192.168.1.10 web01
web02.prod.example.com 192.168.1.11 web02
db01.prod.example.com 192.168.1.20 db01
bastion.prod.example.com 10.0.0.5 bastion
  • ([0-9.]+) → groupe 1 capture l’IP
  • ([[:space:]]+) → groupe 2 capture la séparation
  • ([a-z0-9.]+) → groupe 3 capture le hostname

Dans le remplacement, \3\2\1 réinjecte hostname, espace, IP — dans le nouvel ordre.

Workflow complet — patcher un fichier de config pour une migration

Section intitulée « Workflow complet — patcher un fichier de config pour une migration »

Voici le workflow réel utilisé lors d’une migration prod → staging :

Fenêtre de terminal
# 1. Faire une copie de sécurité
cp db.conf db.conf.orig
# 2. Appliquer toutes les transformations en une seule passe
sed -E -i.bak \
-e 's/host[[:space:]]*=[[:space:]]*.*/host=db.staging.example.com/' \
-e 's/database[[:space:]]*=[[:space:]]*.*/database=staging/' \
-e 's/[[:space:]]*=[[:space:]]*/=/' \
-e '/^#/d' \
-e '/^$/d' \
db.conf
# 3. Vérifier le résultat
cat db.conf
# 4. Vérifier la différence avec l'original
diff db.conf.orig db.conf

Résultat de cat db.conf :

host=db.staging.example.com
port=5432
user=admin
password=secret123
database=staging
max_connections=100
connect_timeout=30

Résultat du diff :

1,3c1,2
< # Configuration base de données
< host = db.internal.example.com
< port = 5432
---
> host=db.staging.example.com
> port=5432
5,9c4,7
< password= secret123
< database=production
< max_connections = 100
< # timeout en secondes
< connect_timeout= 30
---
> password=secret123
> database=staging
> max_connections=100
> connect_timeout=30

Le diff après sed -i est votre vérification obligatoire avant de livrer le fichier.

Par défaut, sed affiche toutes les lignes (même non modifiées). L’option -n supprime cet affichage automatique. La commande p affiche explicitement la ligne.

Combinés, ils permettent un grep orienté ligne structurée :

Fenêtre de terminal
# Afficher seulement les lignes avec code 500 dans access.log
sed -n '/\" 500/p' access.log
192.168.1.10 - alice [01/Apr/2026:08:17:30 +0000] "PUT /api/orders/7 HTTP/1.1" 500 0
PiègeSymptômeSolution
Oublier /gSeule la première occurrence est remplacéeAjouter /g au flag
sed -i sans backupFichier original perdu en cas d’erreurUtiliser -i.bak systématiquement
Confondre BRE et ERE+, ? non reconnus sans backslashAjouter -E pour ERE
Slash / dans le patternErreur de parsingUtiliser un autre délimiteur : `s
Point . non échappéMatche trop largeÉchapper : \. pour un point littéral
Modifier le fichier vendeurPerdu à la prochaine mise à jour du paquetCopier dans /etc/<service>/conf.d/ avant de modifier
  • s/avant/après/g : substitution globale sur chaque ligne
  • -i.bak : modification in-place avec backup — toujours en production
  • Adresse numérique 2s/... ou regex /pattern/s/... pour cibler des lignes
  • /pattern/d : supprimer les lignes qui correspondent
  • -e : enchaîner plusieurs commandes en une passe
  • -E : activer ERE pour +, ?, {n,m}, groupes de capture (...)
  • \1, \2 : réinjecter un groupe capturé dans le remplacement
  • -n ... p : afficher seulement les lignes sélectionnées (comme grep)
  • Vérifier avec diff après tout sed -i sur un fichier de config

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn