Remplacer un chaine de caractère avec la commande sed


plume
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" {} \;

Autres articles du même sujet


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.

    RépondreRépondre
    pti-seb , le 12 décembre 2007 à 18:41
  •  

    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.

    RépondreRépondre
    Laurent Rineau , le 12 décembre 2007 à 18:32
  •  

    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.

    RépondreRépondre
    moi , le 12 décembre 2007 à 19:06
  •  

    @moi :
    1/ Ta notion « d'élégant » est très douteuse. :-) 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.
    2/ Tu n'as pas lu ce que j'ai écris : ta copie est inutile, avec une option "-i.orig" à sed.

    RépondreRépondre
    Laurent Rineau , le 12 décembre 2007 à 19:17
  •  

    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 ;)

    RépondreRépondre
    krusaf , le 12 décembre 2007 à 19:25
  •  

    @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é.

    RépondreRépondre
    pti-seb , le 12 décembre 2007 à 19:28
  •  

    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...

    RépondreRépondre
    liberforce , le 12 décembre 2007 à 19:41
  •  

    @liberforce : j'ai fait la modification du script afin d'ajouter les guillemets.

    RépondreRépondre
    pti-seb , le 12 décembre 2007 à 19:55
  •  

    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+

    RépondreRépondre
    Nicolargo , le 12 décembre 2007 à 21:21
  •  

    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.

    RépondreRépondre
    moi , le 12 décembre 2007 à 23:08
  •  

    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)

    RépondreRépondre
    Temet , le 14 décembre 2007 à 11:35
  •  

    @Nicolargo, @moi, @Temet : merci pour les infos.

    RépondreRépondre
    pti-seb , le 14 décembre 2007 à 11:38
  •  

    Y a pas a dire, le bash c'est vraiment util :) .

    RépondreRépondre
    scraly , le 18 décembre 2007 à 10:18
  •  

    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 :)

    RépondreRépondre
    scraly , le 18 décembre 2007 à 11:45
  •  

    @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.

    RépondreRépondre
    pti-seb , le 19 décembre 2007 à 17:25
  •  

    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

    RépondreRépondre
    Muss , le 23 février 2009 à 14:57
  •  

    @Muss : essaye comme ceci :

    sed -e "s/date=2008Fev22/date=20080222/g" fichier

    RépondreRépondre
    pti-seb , le 23 février 2009 à 16:29
  •  

    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 :-)

    RépondreRépondre
    Muss , le 23 février 2009 à 21:29
  •  

    J'ai essaye ce script. Mais ça ne me donne rien. Aucun fichier n'est modifie.

    #!/bin/sh
    echo enter file name with extension
    read NAME
    echo enter expression to replace
    read FIND
    REPLACE=""
    find . -name $NAME -type f | xargs sed -i -e 's/$FIND/$REPLACE/g'

    RépondreRépondre
    heyyo , le 30 novembre 2009 à 16:44
  •  

    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 :o )

    RépondreRépondre
    liza74 , le 31 août 2011 à 12:18
  •  

    @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' {}

    RépondreRépondre
    KoHead , le 31 août 2011 à 15:13
  •  

    nickel merci ! tes collègues chez qui je suis tombé n'expliquaient pas comment échapper les car spéciaux.

    RépondreRépondre
    laloune , le 23 septembre 2011 à 13:56
  •  

    @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

    RépondreRépondre
    ecomputerclass , le 23 janvier 2012 à 02:38
 

Ajouter un commentaire

actualité apache apple astuce astuces bash bilboblog blog boot chrome clavier commande commandes conky crack date debian Desktop développement exploit faille fedora firefox flash gimp gnome google graphique Graphisme hack hacking Hardware intel internet iphone jackalope jailbreak jaunty Jeux Kde kernel libre Linux log logiciels Logiciels Libres lucid lynx maemo mail maquette microblog microsoft mini-blog mobile mockup monitoring mozilla multi-touch musique mysql n900 nautilus nokia noyau openoffice open source password photos php Planet plugins publicité red hat redhat rpm réseau screenshot script serveurs shell sql ssh statistiques system sécurité thème tux-planet tv twitter ubuntu unity vidéo vidéos vlc voyage wallpaper windows wordpress yum