Remplacer un chaine de caractère avec la commande sed
![]()
Voici une petite astuce bien pratique qui permet de changer une chaîne de caractères par une autre, contenue dans un fichier texte. Tout ceci se réalise en une seule ligne de commande, grâce à sed.
Voici un exemple d'utilisation :
sed -i -e "s/chaines1/chaine2/g" fichier
A noter que si la chaîne contient des caractères spéciaux, on devra les échapper avec '\'. Voici un exemple oû l'on remplace "/home" par "/tmp" :
sed -i -e "s/\/home/\/tmp/g" fichier
Si on a besoin de remplacer une chaîne par une autre pour toute une liste de fichiers contenue dans un répertoire, on pourra utiliser ce petit script basé sur le même principe :
#!/bin/bash
for file in *.txt
do
echo "Traitement de $file ..."
sed -i -e "s/chaine1/chaine2/g" "$file"
done
Ce dernier va :
1. établir la liste de tous les fichiers dont l'extension est .txt
2. puis effectuer le remplacement
Edit : une autre méthode donnée en commentaire qui utilise la commande find et qui permet de traiter des sous-dossier en plus :
find . -name "*.txt" -type f -exec sed -i "s/chaine1/chaine2/g" {} \;


Créé en 2005, Tux-planet est un site qui a pour ambition de regrouper des articles sur Linux et le monde des logiciels libres. 





23 Commentaires pour "Remplacer un chaine de caractère avec la commande sed"
Flux des commentaires de cet article Ajouter un commentaire@Laurent Rineau : merci pour l'info, c'est vrai que dans le cas du script qui peut modifier énormément de fichiers, cela peut être très utile. Je modifie mes commandes.
Si tu utilises GNU/sed, tu peux utiliser l'option -i pour te faciliter la vie. Ton premier exemple se transforme en :
sed -i -e "s/chaines1/chaine2/g" fichier
et ton deuxième exemple, le script bash, se transforme en :
sed -i -e "s/chaine1/chaine2/g" *.txt
Si tu mets un truc après l'option -i, sed crée des backups. Exemple :
sed -i.bak -e "s/chaine1/chaine2/g" *.txt
va modifier tous les *.txt et va créer des backups *.txt.bak.
Au-lieu de "for ...", find peut être plus élégant.
find . -name "*.txt" [+ plein de conditions] -exec cp -p {} {}.orig \; -exec sed -i "s/tralala/trilili/g" {} \;
Le premier "-exec" fait une copy.
@moi :
Moi je préfère largement utiliser les boucles for du shell que find. Notamment avec le shell Zsh le glob permet d'avoir n'importe quelle condition, comme find et même plus.
1/ Ta notion « d'élégant » est très douteuse.
2/ Tu n'as pas lu ce que j'ai écris : ta copie est inutile, avec une option "-i.orig" à sed.
A note r: Plutôt que protéger le caractère / car vous utilisez le caractère / comme séparateur, utilisez plutôt le caractère #
Exemple :
sed -e "s/\/home/\/tmp/g" fichier > fichier.tmp && mv -f fichier.tmp fichier
Plus facile :
sed -e "s#/home#/tmp#g" fichier > fichier.tmp && mv -f fichier.tmp fichier
Ca peut sauver la vie dans des scripts
@moi : c'est vrai que je n'avais pas pensé au find.
Mais l'avantage du script est que l'on peux facilement rajouter d'autres opérations. Maintenant find à l'avantage de traiter les sous-repertoires de façon bien plus simple.
@krusaf : c'est noté.
C'est clair que pour le coup un for est largement plus clair que find. Find vaut le coup quand les fichiers à modifier sont plus difficiles à retrouver.
Par contre, pense à utiliser les guillemets doubles pour les noms de fichiers ("$file") au cas où tu tombes sur des noms avec des espaces...
@liberforce : j'ai fait la modification du script afin d'ajouter les guillemets.
J'avais écrit un billet sur le sujet: blog.nicolargo.com/2007/0...
La méthode utilisait Perl:
# find ./ -type f | xargs perl -pi -w -e 's/titi/tata/g'
a+
Pour Nicolargo
Préfères :
$ find ... -print0 | xargs -0 ....
Ainsi les noms de fichiers qui ont un retour chariot ne posent pas de problème.
Tiens au fait, j'avais fait un 'ti post sur les expressions régulières avec "sed" en exemple.
Si ça t'intéresse : temet79.free.fr/index.php...
(désolé pour le lien à rallonge)
@Nicolargo, @moi, @Temet : merci pour les infos.
Y a pas a dire, le bash c'est vraiment util
.
Si l'on veut faire une modification dans plusieurs fichiers qui sont dans plusieurs répertoires,
est ce qu'un "for file in */*.txt" peut fonctionner ?
merci
@scraly : en mettant */*.txt tu ne traitera que les fichier txt contenu dans des sous-répertoire. les fichiers dans le répertoire courant, tous ceux contenu dans des sous-sous-répertoire ne seront pas pris en compte.
Bonjour,
J'ai une petite question... Si quelqu'un peut m'aider ça serait cool
Je voudrai modifier des caractéres dans une chaine de caractére, sachant qu'elle est contenu dans une variable. Est-ce que "sed" peut le faire?
Je vous pose mon problème... En fait j'ai un format de date qui est le suivant:
date=2008Fev22 (22 Fevrier 2008). Et je voudrai remplacer le Fev par un 02. Peut-on avec sed, spécifier la variable "date" pour que la modification se fasse que sur la variable et non sur un fichier???
Merci pour vos réponse
Mus
@Muss : essaye comme ceci :
ma variable date=`grep EMS /var/adm/syslog/syslog.log | awk '{print $1 $2 $3}'`
echo $date
==> 2008Fev22
je voudrai une commande qui puisse chnager le "Fev" en "02" juste en spécifiant la variable...
Merci pour votre aide
J'ai essaye ce script. Mais ça ne me donne rien. Aucun fichier n'est modifie.
Bonjour,
je souhaiterai modifier une chaine de caractere dans plusieurs fichier mais mon problème est que ce remplacement de chaîne de caractère est different d'un fichier à un autre.
J'ai pensé mettre trois colonne dans un fichier exel : la premiere contiendrait la liste des fichier à midifier la deuxième la chaine de caractère à remplacer et enfin la troisième la nouvelle chaine de caractère.
quelqu'un aurait une petite idée?
Merci
)
@liza74 : Pour chaque fichier voulus tu fais ta modif en combinant sed a find :
find . -name monfichier -type f --exec sed -i -e 's/$FIND/$REPLACE/g' {}
nickel merci ! tes collègues chez qui je suis tombé n'expliquaient pas comment échapper les car spéciaux.
@Muss : La meilleur et simple facon de modifier la date en linux est la suivante:
#date 022215302008
avec: 02 representant le mois
22 representant le jour
1530 representant l'heure et les minutes
2008 representant l'annee