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


32 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
  •  

    Bonjour svp quelqu'un pulse m'aider !!!
    je veux fair un script que je lui passe en parameter un nom et qu'il efface un # qui se trouve au début de cette ligne qui contient ce nom

    RépondreRépondre
    hamza , le 19 mars 2012 à 10:00
  •  

    @hamza : si tu espéres encore une réponse ou pour d'autres qui réinterrogeraient de savoir comment faire:

    echo "### tomy"| sed -e "s/^##* *//"

    Fonctionne quelque-soit le nombre de # et supprime les éventuels espaces devant le nom.

    RépondreRépondre
    tomylee , le 9 mai 2012 à 09:38
  •  

    merci bqq cv j'ai passé cette etape mtn je veux supprimer une chaine dans un fichier sans supprimer tous le contenue de fichier

    RépondreRépondre
    hamza , le 9 mai 2012 à 10:43
  •  

    echo "### début-chaîne-à-supprimer-fin le reste de mon fichier" > fichier.txt

    sed -i "s/début.*fin//" fichier.txt

    ou supprimer simplement le mot chaîne du fichier.txt:

    sed -i "s/chaîne//" fichier.txt

    RépondreRépondre
    tomylee , le 9 mai 2012 à 11:40
  •  

    non c pas je veux supprimer une chaine dans un fichier cfg
    la chaine est variable que je la passe en parametre dans un script shell sous php !!
    shell_exet("script.sh".$chaine);
    mon prob que le script ne connais jamais la chaine par contre si je fait un echo avan just shell-exec je vois ma chaine

    RépondreRépondre
    hamza , le 9 mai 2012 à 12:21
  •  

    script.sh:
    #!/bin/bash
    sed -i "s/$1//" fichier.cfg

    shell_exec('sh script.sh ' . $chaine)

    RépondreRépondre
    tomylee , le 9 mai 2012 à 13:49
  •  

    ouiii c bien exatement ca !! mon probleme que le script ne connais pas mon variable($chaine)!!
    j'ai vu au log (not found)!!!!je comprend pas pk

    RépondreRépondre
    hamza , le 9 mai 2012 à 14:17
  •  

    Bonjour,

    Dans mon cas, je veux remplacer crocher "[" par un blanc, voici ma syntaxe : sed s'/[//g' , mais ca me donne l'erreur suivante : sed: -e expression #1, char 6: unterminated `s' command.

    Merci

    RépondreRépondre
    redaamine , le 10 décembre 2013 à 15:37
  •  

    Bonjour,
    J'utilise un script dans ce genre :
    find . -name "*.php" -type f -exec sed -i "s/chaine1/chaine2/g" {} \;

    Le problème est que tous mes fichiers php voient leur date modifiée, même s'ils ne sont pas concernés par le remplacement, ce qui est problématique pour moi. Qui connaîtrait le moyen de ne modifier que les fichiers concernés par la substitution ?

    RépondreRépondre
    Christophe , le 9 juin 2014 à 14:29
 

Ajouter un commentaire

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