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 :
- produire la transformation sur
stdout; - vérifier le résultat ;
- écrire éventuellement vers un nouveau fichier ;
- 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
bout; - les scripts
sedcomplexes ; - les différences détaillées entre GNU
sed, BSDsedet les autres implémentations ; - les expressions régulières avancées ;
- l’utilisation de
sed -icomme 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
- GNU sed manual — GNU Project
- GNU sed manual — sed scripts — GNU Project
- GNU sed manual — The "s" Command — GNU Project
- GNU sed manual — Command-Line Options — GNU Project
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.
