Linux sans magie #26 — sed : remplacer, supprimer et transformer du texte sans ouvrir d’éditeur

Comprendre sed pour remplacer, supprimer, sélectionner et transformer du texte dans un fichier ou un pipeline, sans modifier les données d’origine par défaut.

Dans l’article précédent, nous avons utilisé grep, cut, sort, uniq et wc pour filtrer, extraire et compter des informations dans un flux texte.

sed ajoute une capacité différente : transformer le texte lui-même.

Il peut remplacer une chaîne, supprimer certaines lignes, n’afficher qu’une partie d’un fichier ou appliquer une transformation à chaque ligne d’un flux. Le tout sans ouvrir d’éditeur interactif.

L’objectif ici n’est pas d’apprendre tout le langage sed. Nous allons rester sur quelques opérations fondamentales, suffisamment simples pour être comprises et combinées dans des pipelines.

sed est un éditeur de flux

GNU sed est un stream editor : il lit une entrée, applique des commandes au texte traité et écrit le résultat sur sa sortie standard.

Dans sa forme la plus simple :

sed 'COMMANDE' fichier.txt

Par défaut, sed ne modifie pas le fichier d’origine. Il produit une version transformée sur stdout.

C’est un point essentiel pour l’apprentissage : on peut expérimenter sans écraser immédiatement le fichier source.

Prenons un exemple :

printf 'serveur=dev\n' > configuration.txt
sed 's/dev/prod/' configuration.txt

Résultat affiché :

serveur=prod

Mais le fichier reste inchangé :

cat configuration.txt

Résultat :

serveur=dev

sed a transformé le flux de sortie, pas le fichier lui-même.

La commande s : remplacer du texte

La forme la plus connue est :

s/ancien/nouveau/

Le s signifie substitute.

Exemple :

printf 'environnement=dev\n' | sed 's/dev/prod/'

Résultat :

environnement=prod

Le premier élément après s/ est le motif recherché. Le second est le texte de remplacement.

Sur un fichier :

sed 's/dev/prod/' configuration.txt

Le résultat transformé est envoyé vers stdout.

Une substitution remplace la première occurrence de la ligne

Considérons :

printf 'dev dev dev\n' | sed 's/dev/prod/'

Résultat :

prod dev dev

Sans modificateur supplémentaire, la commande s remplace la première correspondance trouvée sur chaque ligne.

Pour remplacer toutes les occurrences correspondantes d’une ligne, ajoutez le modificateur g :

printf 'dev dev dev\n' | sed 's/dev/prod/g'

Résultat :

prod prod prod

Le g signifie ici que la substitution doit être appliquée globalement sur la ligne.

Utiliser un autre séparateur

Le caractère / n’est pas obligatoire comme séparateur de la commande s.

C’est utile lorsqu’on manipule des chemins.

Cette commande est valide :

printf '/var/www/html\n' | sed 's#/var/www#/srv/web#'

Résultat :

/srv/web/html

Avec # comme séparateur, le chemin reste plus lisible qu’avec plusieurs caractères d’échappement.

Le principe ne change pas :

s#ancien#nouveau#

Supprimer des lignes avec d

La commande d supprime du flux la ligne sélectionnée.

Créons un fichier de laboratoire :

cat > services.txt <<'EOF'
web:active
api:inactive
db:active
cache:inactive
worker:active
EOF

Pour supprimer les lignes contenant inactive :

sed '/inactive/d' services.txt

Résultat :

web:active
db:active
worker:active

L’expression /inactive/ sélectionne les lignes correspondant au motif, puis d les supprime du flux produit.

Le fichier services.txt n’est pas modifié.

Appliquer une commande à une ligne précise

sed peut aussi utiliser un numéro de ligne comme adresse.

Pour supprimer la deuxième ligne :

sed '2d' services.txt

Pour remplacer du texte uniquement sur la troisième ligne :

sed '3s/active/maintenance/' services.txt

Ici, le 3 indique que la substitution ne doit être appliquée qu’à la troisième ligne.

Cette logique est importante : une commande sed peut être précédée d’une adresse qui détermine les lignes auxquelles elle s’applique.

Appliquer une substitution uniquement aux lignes correspondantes

On peut combiner une adresse basée sur un motif et une commande de substitution.

Exemple :

sed '/worker/s/active/maintenance/' services.txt

Résultat :

web:active
api:inactive
db:active
cache:inactive
worker:maintenance

La substitution n’est exécutée que sur les lignes correspondant au motif worker.

On peut lire cette commande de gauche à droite :

/worker/               → sélectionner les lignes contenant worker
s/active/maintenance/  → remplacer active par maintenance

-n et p : n’afficher que ce qui nous intéresse

Par défaut, sed imprime chaque ligne après traitement.

L’option -n désactive cette impression automatique.

La commande p permet ensuite d’imprimer explicitement les lignes sélectionnées.

Exemple :

sed -n '/active/p' services.txt

Attention toutefois à notre jeu de données : le texte inactive contient lui aussi la chaîne active.

Avec un simple motif active, les lignes inactive correspondent donc également.

Pour notre format nom:état, nous pouvons rechercher la fin exacte de ligne :

sed -n '/:active$/p' services.txt

Résultat :

web:active
db:active
worker:active

Cette commande signifie :

-n          → ne rien imprimer automatiquement
/:active$/  → sélectionner les lignes se terminant par :active
p           → imprimer les lignes sélectionnées

Afficher une plage de lignes

Une adresse peut aussi représenter une plage.

Pour afficher les lignes 2 à 4 :

sed -n '2,4p' services.txt

Résultat :

api:inactive
db:active
cache:inactive

Ce type de commande est pratique pour inspecter une portion précise d’un fichier sans ouvrir un éditeur.

sed dans un pipeline

Comme les outils vus précédemment, sed lit aussi depuis stdin.

Exemple :

printf 'dev\ntest\nprod\n' | sed 's/dev/developpement/'

Ou après une autre commande :

grep 'inactive' services.txt | sed 's/:inactive/:disabled/'

Résultat :

api:disabled
cache:disabled

Le fichier original n’est toujours pas modifié.

Le pipeline peut être lu simplement :

grep → sélectionne les lignes inactive
sed  → transforme inactive en disabled

Lab : transformer un fichier sans toucher à l’original

Créons un répertoire de travail dédié :

mkdir -p /tmp/linux-sans-magie-26
cd /tmp/linux-sans-magie-26

Puis notre fichier :

cat > applications.conf <<'EOF'
web=dev
api=dev
db=prod
cache=dev
legacy=disabled
EOF

Étape 1 — remplacer la première occurrence par ligne

sed 's/dev/test/' applications.conf

Les lignes contenant dev sont affichées avec test à la place.

Étape 2 — supprimer une ligne selon un motif

sed '/legacy/d' applications.conf

La ligne contenant legacy disparaît de la sortie.

Étape 3 — sélectionner uniquement certaines lignes

sed -n '/=dev$/p' applications.conf

Résultat attendu :

web=dev
api=dev
cache=dev

Étape 4 — combiner sélection et transformation

sed '/^api=/s/dev/test/' applications.conf

Résultat attendu :

web=dev
api=test
db=prod
cache=dev
legacy=disabled

Seule la ligne commençant par api= est transformée.

Étape 5 — enregistrer le résultat dans un autre fichier

Si le résultat vous convient, utilisez une redirection vers un nouveau fichier :

sed 's/dev/test/g' applications.conf > applications-test.conf

Vérifiez ensuite :

cat applications-test.conf

Cette méthode conserve le fichier d’origine et rend la transformation facile à comparer.

Vérifier avant de remplacer un fichier

Avant toute modification réelle, affichez le résultat :

sed 's/dev/test/g' applications.conf

Puis comparez une version générée avec l’original :

sed 's/dev/test/g' applications.conf > applications-test.conf
diff -u applications.conf applications-test.conf

Cette approche donne une vérification observable avant toute écriture sur le fichier d’origine.

Elle est particulièrement utile pour les fichiers de configuration.

À propos de sed -i

GNU sed propose l’option -i, qui permet d’éditer un fichier directement sur place.

C’est pratique, mais cela change complètement le niveau de risque : le fichier source peut être modifié immédiatement.

Dans cet article, nous ne l’utilisons donc pas dans le lab principal.

Pour apprendre sed, il est plus sûr de :

  1. produire la transformation sur stdout ;
  2. vérifier le résultat ;
  3. écrire éventuellement vers un nouveau fichier ;
  4. remplacer l’original seulement lorsqu’on a explicitement décidé de le faire.

Les détails et variantes de -i peuvent aussi différer entre implémentations de sed. Il vaut donc mieux consulter la documentation de l’environnement concerné avant de l’utiliser dans un script portable.

Diagnostiquer une commande sed

Quand une expression devient difficile à comprendre, décomposez-la.

Pour :

sed '/^api=/s/dev/test/g' applications.conf

on peut raisonner ainsi :

/^api=/    → lignes commençant par api=
s          → substitution
dev        → texte recherché
test       → texte de remplacement
g          → toutes les occurrences correspondantes de la ligne

Si le résultat n’est pas celui attendu, testez d’abord uniquement l’adresse :

sed -n '/^api=/p' applications.conf

Puis ajoutez la substitution.

Cette méthode évite de modifier plusieurs éléments de l’expression en même temps.

Bonnes pratiques

Utilisez sed pour des transformations textuelles simples et explicites.

Prévisualisez les changements avant d’écrire un fichier.

Lorsque le caractère / rend une substitution illisible, choisissez un autre séparateur :

sed 's#/ancien/chemin#/nouveau/chemin#' fichier

Pour les sélections complexes, vérifiez d’abord les lignes ciblées avec -n et p.

Gardez aussi à l’esprit que les motifs utilisés par sed sont des expressions régulières. Même dans des exemples simples, certains caractères ont donc un sens particulier.

Enfin, si une transformation commence à nécessiter de nombreuses conditions, plusieurs champs et des calculs, un outil comme awk peut devenir plus lisible.

Sécurité et points de vigilance

Une commande sed qui écrit seulement sur stdout est relativement simple à vérifier.

Le risque augmente dès que la sortie est redirigée vers un fichier existant ou que l’on utilise une modification en place.

Évitez notamment une construction de ce type :

sed 's/dev/prod/g' fichier.conf > fichier.conf

Le shell ouvre et tronque le fichier de destination avant que sed ait fini de le lire. Cette construction peut donc détruire son contenu.

Utilisez un autre fichier de sortie :

sed 's/dev/prod/g' fichier.conf > fichier-nouveau.conf

puis comparez les deux fichiers avant tout remplacement.

Les transformations automatiques peuvent aussi modifier des informations sensibles ou des valeurs de configuration critiques. Sur un fichier important, travaillez sur une copie et conservez un moyen de revenir à l’état précédent.

Coûts

Les commandes présentées ici utilisent des outils locaux de traitement de texte. Elles n’introduisent pas de coût de service ou de ressource cloud.

Limites de cet article

Nous ne couvrons pas ici :

  • les commandes avancées du langage sed ;
  • le hold space ;
  • les traitements multilignes ;
  • les branchements avec b ou t ;
  • les scripts sed complexes ;
  • les différences détaillées entre GNU sed, BSD sed et les autres implémentations ;
  • les expressions régulières avancées ;
  • l’utilisation de sed -i comme mécanisme principal d’automatisation.

Le but reste de maîtriser les opérations de base avant d’ajouter de la complexité.

Rollback et nettoyage

Le lab principal ne modifie pas le fichier source directement.

Pour nettoyer :

rm -rf /tmp/linux-sans-magie-26

Cette commande cible uniquement le répertoire temporaire créé explicitement pour l’exercice.

Si vous avez appliqué sed à un vrai fichier de configuration en dehors de ce lab, le rollback dépend de la copie ou sauvegarde que vous avez créée avant modification.

Références officielles

Conclusion

sed devient beaucoup plus simple lorsqu’on le voit comme un outil qui reçoit du texte, applique une transformation et renvoie un nouveau flux.

Les mécanismes fondamentaux à retenir sont :

s/ancien/nouveau/  → remplacer
g                  → remplacer toutes les occurrences correspondantes de la ligne
d                  → supprimer les lignes sélectionnées
-n ... p           → afficher uniquement les lignes choisies
adresse + commande → limiter une transformation à certaines lignes

Avec ces quelques éléments, on peut déjà automatiser de nombreuses transformations simples tout en gardant une méthode sûre : prévisualiser, vérifier, puis seulement décider d’écrire le résultat.