Bash : remplacer des chaines par d'autres ans un fichier

Résolu
mortelrdv -  
 mortelrdv -
Bonjour,

je suis SunOS ajamei1u1 5.10 Generic_147441-01 i86pc i386 i86pc

j'ai un fichierA contenant une liste de chaines à remplacer par d'autres dans un fichierB.
fichierA
aaa;bbbbb
ddd;zzz
hhh;kkk


et donc en gros je veux remplacer dans le fichierB :
aaa -----> bbbbb
ddd -----> zzz
hhh -----> kkk

je peux faire un truc du genre
sed -i "s/aaa/bbbbb" fichierB   au tant de fois (avec boucle) qu'il y a de ligne dans le fichierA (x fois ouverture/fermeture de fichierB, ça fait travailler le disque)

il y a peut etre une meilleur solution (qui sait), Comment y prendriez vous ?


Merci

PS : sachant que le fichierA peut contenir  plus de 300 lignes et que le fichierB peut contenir  plus de 7000 lignes.


5 réponses

  1. mamiemando Messages postés 33174 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    Déjà pour les remplacements de sed j'ajouterais un "/g" à la fin pour que toutes les occurrences d'un motif dans un ligne soient substituées. Ensuite la manière de rendre tout ça efficace, c'est d'enchaîner les sed à la volée (-e) via des pipes (|) au lieu de faire la modifications dans le fichier lui même (-i) :

    (mando@silk) (~) $ cat toto.txt  
    aaa;bbbb 
    ddd;zzz 
    hhh;kkk 
    
    (mando@silk) (~) $ sed -e "s/bbbb/aaa/g" toto.txt  | sed -e "s/ddd/zzz/g" | sed -e "s/hhh/kkk/g" > tata.txt 
    
    (mando@silk) (~) $ cat tata.txt  
    aaa;aaa 
    zzz;zzz 
    kkk;kkk


    Bonne chance
    0
    1. mortelrdv
       
      oui, mais là c'est un cas simple.
      mais dans le cas où le fichierA contient plein de possibilité de remplacement, mettre tout ça sur une ligne de commande c'est invivable.

      de plus je me vois mal de faire des lignes de sed de cette longueur à chaque fois que le contenu du fichierA change (on n'en finira plus avec les copier/coller :) )
      0
  2. zipe31 Messages postés 34620 Date d'inscription   Statut Contributeur Dernière intervention   6 502
     
    Salut,

    $ head fich*
    ==> fichA <==
    aaa;bbbbb
    ddd;zzz
    hhh;kkk
    
    ==> fichB <==
    aaa -----> bbbbb
    ddd -----> zzz
    hhh -----> kkk
    
    $ OIFS="${IFS}";IFS=";"
    while read cA cB
    do 
    sed -i "s/${cA}/${cB}/g" fichB
    done < fichA
    IFS="${OIFS}"
    
    $ head fich*
    ==> fichA <==
    aaa;bbbbb
    ddd;zzz
    hhh;kkk
    
    ==> fichB <==
    bbbbb -----> bbbbb
    zzz -----> zzz
    kkk -----> kkk
    
    $

    0
    1. zipe31 Messages postés 34620 Date d'inscription   Statut Contributeur Dernière intervention   6 502
       
      Ah tiens, je viens de faire un essai assez concluant ma foi ;-))

      Plutôt que de s'embêter avec la variable ${IFS}, j'ai carrément pris la ligne dans sa totalité, mais par contre j'ai changé le séparateur par défaut de "sed", qui est le slash pour rappel, par celui contenu dans le fichA, à savoir le point virgule (;), et ça marche ;-))

      $ while read line;do sed -i.bak "s;${line};g" fichB;done < fichA
      
      $ cat fichB
      bbbbb -----> bbbbb
      zzz -----> zzz
      kkk -----> kkk
      
      $


      Enjoy ;-))
      0
  3. Utilisateur anonyme
     
    salut,

    sed "$(sed 's/^/s\//; s/;\|$/\//g' fichierA)g" fichierB
    0
    1. zipe31 Messages postés 34620 Date d'inscription   Statut Contributeur Dernière intervention   6 502
       
      Aussi* ;-))


      * Comme Félicie ;-)
      0
  4. mamiemando Messages postés 33174 Date d'inscription   Statut Modérateur Dernière intervention   7 944
     
    J'avais mal lu lors de ma première réponse, ci-dessous un script shell qui répond à la remarque :
    https://forums.commentcamarche.net/forum/oldest/26751996-bash-remplacer-des-chaines-par-d-autres-ans-un-fichier#2

     #!/bin/bash
    
    conf="subst.txt"
    in="toto.txt"
    out="titi.txt"
    cmd="cat $in"
    
    while read line
    do
        a="$(echo $line | cut -d';' -f1)"
        b="$(echo $line | cut -d';' -f2)"
        cmd="$cmd | sed -e \"s/$a/$b/g\""
    done < $conf
    cmd="$cmd > $out"
    eval $cmd


    ... avec le fichier subst.txt qui contient :

    aaa;bbbbb
    ddd;zzz
    hhh;kkk


    ... et toto.txt le fichier sur lequel on se base pour générer le fichier titi.txt.

    Ceci dit, la solution https://forums.commentcamarche.net/forum/oldest/26751996-bash-remplacer-des-chaines-par-d-autres-ans-un-fichier#6 est plus concise :-)

    Bonne chance
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. mortelrdv
     
    Bonjour,

    Merci de vos propositions

    Cdlt
    0