Replacer texte sur la première occurrence du fichier

Résolu
Nyser -  
mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   -

Bonjour,

Je cherche a écrire un script qui va modifier des informations sur des fichiers générés automatiquement. Mon fichier ressemble initialement à ça  :

toto 1111
tata 1234
toto 1111

J'aimerais changer uniquement le 1er "toto 1111" en "toto 1269" avec la commande sed
J'arrive a le changer les deux toto avec l'indice de substitution s mais même sans mettre le g pour l'appliquer à tout le fichier, il me modifie les deux. 

Merci d'avance pour vos réponses.  

5 réponses

  1. xHaMaz Messages postés 123 Date d'inscription   Statut Membre Dernière intervention   18
     

    Bonjour

    sed '1s/^toto 1111$/toto 1269/' inputfile.txt > outputfile.txt
    

    Essaye ça

    1
  2. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     

    hello

    $ awk '/toto/ && !n++ {$2=1269} {print $0}' fichier
    
    toto 1269
    
    tata 1234
    
    toto 1111
    
    $ sed '0,/toto/{s/1111/1269/}'  fichier
    
    toto 1269
    
    tata 1234
    
    toto 1111
    $ 
    
    
    1
  3. Nyser
     

    Ca n'a pas marché, ça ne modifie rien

    Mais merci pour la tentative et la réactivité ;)

    0
    1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
       

      La commande marche mais le résultat est généré dans un autre fichier (outputfile.txt). Il faut de plus veiller à ce que la ligne soit exactement conforme (pas d'espace en plus). La commande cat -A permet de vérifier en affichant $ en fin de ligne.

      Ensuite, la commande fournie par xHaMaz génère le résultat dans un autre fichier. Si tu tu veux que la substitution soit faite en place dans le fichier d'entrée (disons input.txt), il faut utiliser l'option -i.

      (mando@silk) (~) $ cat -A input.txt
      toto 1111$
      tata 1234$
      toto 1111$
      
      (mando@silk) (~) $ sed -i '1s/^toto 1111$/toto 1269/' input.txt
      
      (mando@silk) (~) $ cat -A input.txt
      toto 1269$
      tata 1234$
      toto 1111$

      Bonne chance

      1
      1. Nyser Messages postés 4 Date d'inscription   Statut Membre Dernière intervention   > mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention  
         

        Waow ! super, merci pour ces explications ! 

        0
  4. Nyser Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
     

    Merci, en effet ça fonctionne ! j'utilise la commande sed. 

    Pourrais-tu m'expliquer à quoi sert le 0 ? 

    Merci d'avance !

    0
    1. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944
       

      La solution #3 proposée par dubcek basée sur sed repose sur la notion de range specifier (voir ici). Expliquons cette notion sur ton exemple :

      • Si tu connais le numéro de ligne (ici 1) sur lequel la modification doit opérer , tu peux écrire :
        sed '1,1s/^toto 1111$/toto 1269/' input.txt
        ou de manière plus laxiste : 
        sed '1,1s/1111/1269/' input.txt
        ... ce qui signifie :
        • sur la plage de ligne allant de 1 à 1 incluses,
        • applique la substitution qui remplace la première occurrence de 1111 par 1269).
      • La commande de dubcek #3 est plus générale, car elle n'a pas d'a priori sur la ligne dans laquelle figure la première occurrence à substituer :
        sed '0,/toto/{s/1111/1269/}' input.txt
        ... ce qui signifie :
        • cherche la première ligne qui est validée par l'expression rationnelle "toto" (donc la première ligne qui contient toto) : c'est une syntaxe spécifique, voir ici
        • puis, applique la substitution qui remplace la première occurrence de 1111 par 1269
        • si tu remplaces le 0 par un entier n strictement positif, la recherche de la ligne se fait pour toutes les lignes validées à partir de la ligne n incluse

      Bonne chance

      1
      1. Nyser Messages postés 4 Date d'inscription   Statut Membre Dernière intervention   > mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention  
         

        Et sais tu s'il est possible de remplacer le début de la recherche (0) dans l'exemple par une adresse ? 

        Je m'explique, à la place cette commande :

        sed '0,/toto/{s/1111/1269/}' input.txt
        

        j'aimerai modifier le 0 mais non pas par un entier mais par une phrase. 

        Par exemple :

        toto 1111
        
        tata 1234
        
        toto 1111
        
        titi 4321
        
        tata 6789
        
        toto 1111

        j'aimerai modifier le dernier toto uniquement et a partir de tata 6789 par exemple. J'imaginai un truc comme ça : 

        sed 'tata 6789,/toto/{s/1111/1269/}' input.txt
        

        Mais ça ne marche pas

        0
      2. mamiemando Messages postés 33228 Date d'inscription   Statut Modérateur Dernière intervention   7 944 > Nyser Messages postés 4 Date d'inscription   Statut Membre Dernière intervention  
         

        Je ne sais pas si tu peux faire comme tu essayes de faire, mais c'est peut-être faisable.

        Personnellement, je pense qu'il devient d'écrire un script shell, dans lequel tu lances une première commande trouve le numéro de ligne de la dernière occurrence de toto.

        j=`grep -n "^toto" fichier.txt | tail -n 1 | cut -d":" -f 1`
        echo "$j"

        ... et une autre le numéro de ligne qui contient "tata 6789" :

        i=`grep -n "^tata 6789$" fichier | head -n 1 | cut -d":" -f 1`
        echo "$i"

        Il faut ensuite contrôler que i et j sont bien définis (donc que les deux motifs cherchés on été trouvés) et comparer i et j (i < j). Dans ce cas, un remplacement est possible, et $j te donne le numéro de ligne où opérer, tu peux utiliser sed et un range specifier basé sur $j. 

        if [[ -z "$i" && -z "$j" && "$i" -lt "$j" ]]
        then
            eval "sed '${j},${j}s/^toto/toto 5678/' fichier.txt"
        fi

        Bon je ne te cache pas que moi je ferais tout ça en python plutôt qu'en shell mais ça c'est affaire de goût :-D

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

    Posez votre question
  6. dubcek Messages postés 18627 Date d'inscription   Statut Contributeur Dernière intervention   5 660
     
    $ sed '/tata 6789/,/toto/s/1111/1269/' input.txt
    toto 1111
    
    tata 1234
    
    toto 1111
    
    titi 4321
    
    tata 6789
    
    toto 1269
    
    0