← retour aux snippets

sed: remplacer du texte en place de façon sûre

Effectuer des remplacements fiables dans un ou plusieurs fichiers, de manière portable et atomique.


objectif

Remplacer une chaîne ou une expression régulière dans des fichiers sans casser la compatibilité Linux/macOS et sans corrompre les fichiers.

code minimal

# portable: écrire via un fichier temporaire puis remplacer (atomique)
tmp="$(mktemp)"; sed -E 's/old/new/g' config.ini > "$tmp" && mv -f "$tmp" config.ini

utilisation

# GNU/Linux: in-place avec sauvegarde, puis suppression du .bak
sed -E -i.bak 's/old/new/g' config.ini && rm -f config.ini.bak

# macOS/BSD: in-place exige un suffixe (même commande que ci-dessus)
sed -E -i.bak 's/old/new/g' config.ini && rm -f config.ini.bak

# plusieurs fichiers: sûr avec find -print0 / xargs -0
find . -type f -name "*.env" -print0 \
  | xargs -0 -I{} sh -c 'set -Eeuo pipefail; sed -E -i.bak "s/^DEBUG=.*/DEBUG=false/" "$1"' sh {}

# remplacer seulement s'il y a correspondance (évite de toucher l'mtime inutilement)
grep -q 'old' config.ini && { tmp="$(mktemp -p . .config.ini.XXXXXX)"; sed -E 's/old/new/g' config.ini > "$tmp" && mv -f "$tmp" config.ini; }

# remplacer une barre oblique sans échapper (changer le délimiteur)
sed -E 's|/api/v1/|/api/v2/|g' routes.txt

variante(s) utile(s)

# mots entiers uniquement
# GNU sed:
sed -E 's/\<token\>/secret/g' app.conf
# BSD/macOS sed:
sed -E 's/[[:<:]]token[[:>:]]/secret/g' app.conf

# ignorer la casse
sed -E 's/foo/bar/Ig' fichier.txt

# capturer et réutiliser (groupes)
sed -E 's/^version=([0-9]+)\.([0-9]+)\.([0-9]+)/version=\1.\2.'"$((PATCH+1))"'/'

# n'agir que sur des lignes matching un préfixe
sed -E '/^PORT=/ s/[0-9]+/8080/' .env

# remplacer entre délimiteurs (ex: balises)
sed -E '/^BEGIN CONFIG$/,/^END CONFIG$/ s/^#?enabled=.*/enabled=true/'

notes

  • pour la portabilité, évitez sed -i sans suffixe sur macOS; utilisez -i.bak puis supprimez la sauvegarde, ou la stratégie mktemp + mv.
  • -E active les regex étendues; adaptez vos motifs en conséquence (escapes plus simples).
  • préférez un délimiteur alternatif (|) lorsque votre motif contient des /.
  • \</\> (mots entiers) est propre à GNU sed; sur BSD/macOS, utilisez [[:<:]] et [[:>:]].
  • l’approche via mktemp + mv est atomique si le temporaire est créé sur le même filesystem (utilisez -p . pour le dossier courant).