Lorsque vous travaillez avec des fichiers texte, vous devrez souvent rechercher et remplacer des chaînes de texte dans un ou plusieurs fichiers.
sed
est un s streamer ed itor. Il peut effectuer une manipulation de texte de base sur des fichiers et des flux d'entrée tels que des pipelines. Avec sed
, vous pouvez rechercher, trouver et remplacer, insérer et supprimer des mots et des lignes. Il prend en charge les expressions régulières de base et étendues qui vous permettent de faire correspondre des modèles complexes.
Dans cet article, nous verrons comment rechercher et remplacer des chaînes avec sed
. Nous vous montrerons également comment effectuer une recherche et un remplacement récursifs.
Rechercher et remplacer la chaîne par sed
#
Il existe plusieurs versions de sed
, avec quelques différences fonctionnelles entre eux. macOS utilise la version BSD, tandis que la plupart des distributions Linux sont livrées avec GNU sed
pré-installé par défaut. Nous utiliserons la version GNU.
La forme générale de recherche et de remplacement de texte à l'aide de sed
prend la forme suivante :
sed -i 's/SEARCH_REGEX/REPLACEMENT/g' INPUTFILE
-i
- Par défaut,sed
écrit sa sortie sur la sortie standard. Cette option indique àsed
pour modifier les fichiers en place. Si une extension est fournie (ex -i.bak), une sauvegarde du fichier d'origine est créée.s
- La commande de substitution, probablement la commande la plus utilisée dans sed./ / /
- Caractère délimiteur. Il peut s'agir de n'importe quel caractère, mais généralement de la barre oblique (/
) est utilisé.SEARCH_REGEX
- Chaîne normale ou expression régulière à rechercher.REPLACEMENT
- La chaîne de remplacement.g
- Drapeau de remplacement global. Par défaut,sed
lit le fichier ligne par ligne et ne change que la première occurrence duSEARCH_REGEX
sur une ligne. Lorsque l'indicateur de remplacement est fourni, toutes les occurrences sont remplacées.INPUTFILE
- Le nom du fichier sur lequel vous souhaitez exécuter la commande.
C'est une bonne pratique de mettre des guillemets autour de l'argument afin que les méta-caractères du shell ne se développent pas.
Voyons comment nous pouvons utiliser le sed
commande pour rechercher et remplacer du texte dans des fichiers avec certaines de ses options et drapeaux les plus couramment utilisés.
À des fins de démonstration, nous utiliserons le fichier suivant :
file.txt123 Foo foo foo
foo /bin/bash Ubuntu foobar 456
Si le g
flag est omis, seule la première instance de la chaîne de recherche dans chaque ligne est remplacée :
sed -i 's/foo/linux/' file.txt
123 Foo linux foo
linux /bin/bash Ubuntu foobar 456
Avec le drapeau de remplacement global sed
remplace toutes les occurrences du modèle de recherche :
sed -i 's/foo/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu linuxbar 456
Comme vous l'avez peut-être remarqué, la sous-chaîne foo
à l'intérieur du foobar
string est également remplacé dans l'exemple précédent. Si ce n'est pas le comportement souhaité, utilisez l'expression de limite de mot (\b
) aux deux extrémités de la chaîne de recherche. Cela garantit que les mots partiels ne correspondent pas.
sed -i 's/\bfoo\b/linux/g' file.txt
123 Foo linux linux
linux /bin/bash Ubuntu foobar 456
Pour rendre le modèle de correspondance insensible à la casse, utilisez le I
drapeau. Dans l'exemple ci-dessous, nous utilisons à la fois le g
et I
drapeaux :
sed -i 's/foo/linux/gI' file.txt
123 linux linux linux
linux /bin/bash Ubuntu linuxbar 456
Si vous souhaitez rechercher et remplacer une chaîne contenant le caractère délimiteur (/
) vous devrez utiliser la barre oblique inverse (\
) pour échapper à la barre oblique. Par exemple pour remplacer /bin/bash
avec /usr/bin/zsh
vous utiliseriez
sed -i 's/\/bin\/bash/\/usr\/bin\/zsh/g' file.txt
L'option la plus simple et la plus lisible consiste à utiliser un autre caractère délimiteur. La plupart des gens utilisent la barre verticale (|
) ou deux-points (:
) mais vous pouvez utiliser n'importe quel autre caractère :
sed -i 's|/bin/bash|/usr/bin/zsh|g' file.txt
123 Foo foo foo
foo /usr/bin/zsh Ubuntu foobar 456
Vous pouvez également utiliser des expressions régulières. Par exemple, pour rechercher tous les nombres à 3 chiffres et les remplacer par la chaîne number
vous utiliseriez :
sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt
number Foo foo foo
foo /bin/bash demo foobar number
Une autre fonctionnalité utile de sed est que vous pouvez utiliser le caractère esperluette &
qui correspond au motif correspondant. Le personnage peut être utilisé plusieurs fois.
Par exemple, si vous souhaitez ajouter des accolades {}
autour de chaque nombre à 3 chiffres, tapez :
sed -i 's/\b[0-9]\{3\}\b/{&}/g' file.txt
{123} Foo foo foo
foo /bin/bash demo foobar {456}
Enfin, c'est toujours une bonne idée de faire une sauvegarde lors de l'édition d'un fichier avec sed
. Pour ce faire, il suffit de fournir une extension pour le fichier de sauvegarde au -i
option. Par exemple, pour éditer le file.txt
et enregistrez le fichier d'origine sous file.txt.bak
vous utiliseriez :
sed -i.bak 's/foo/linux/g' file.txt
Pour vous assurer que la sauvegarde est créée, listez les fichiers avec le ls
commande :
ls
file.txt file.txt.bak
Recherche et remplacement récursifs #
Parfois, vous souhaiterez peut-être rechercher de manière récursive des répertoires pour les fichiers contenant une chaîne et remplacer la chaîne dans tous les fichiers. Cela peut être fait en utilisant des commandes telles que find
ou grep
pour rechercher récursivement des fichiers dans le répertoire et diriger les noms de fichiers vers sed
.
La commande suivante recherchera récursivement les fichiers dans le répertoire de travail actuel et transmettra les noms de fichiers à sed
.
find . -type f -exec sed -i 's/foo/bar/g' {} +
Pour éviter les problèmes avec les fichiers contenant des espaces dans leurs noms, utilisez le -print0
option, qui indique find
pour imprimer le nom du fichier, suivi d'un caractère nul et diriger la sortie vers sed
en utilisant xargs -0
:
find . -type f -print0 | xargs -0 sed -i 's/foo/bar/g'
Pour exclure un répertoire, utilisez le -not -path
option. Par exemple, si vous remplacez une chaîne dans votre référentiel git local pour exclure tous les fichiers commençant par un point (.
), utilisez :
find . -type f -not -path '*/\.*' -print0 | xargs -0 sed -i 's/foo/bar/g'
Si vous souhaitez rechercher et remplacer du texte uniquement sur des fichiers avec une extension spécifique, vous utiliserez :
find . -type f -name "*.md" -print0 | xargs -0 sed -i 's/foo/bar/g'
Une autre option consiste à utiliser le grep
commande pour rechercher de manière récursive tous les fichiers contenant le modèle de recherche, puis diriger les noms de fichiers vers sed
:
grep -rlZ 'foo' . | xargs -0 sed -i.bak 's/foo/bar/g'
Conclusion #
Bien que cela puisse sembler compliqué et complexe, au début, rechercher et remplacer du texte dans des fichiers avec sed
est très simple.
Pour en savoir plus sur sed
commandes, options et drapeaux, consultez le manuel GNU sed et le didacticiel Grymoire sed.
Si vous avez des questions ou des commentaires, n'hésitez pas à laisser un commentaire.