Sed et ses caprices (ou les miens)

Résolu
bkrqpzef Messages postés 213 Statut Membre -  
bkrqpzef Messages postés 213 Statut Membre -
Salut,
il faudrait que je transforme le mot "BATEAU" par un autre mot, par exemple "MAISON". Le mot est contenu dans un fichier du repertoire courant, mais j'ignore lequel, je pensais utiliser :
$sed -i 's/BATEAU/MAISON/' *.*

Malheureusement, il y a plusieurs fichiers qui contiennent le mot BATEAU. Avec cette commande, je les modifie tous. Or je voudrais qu'il s'arrête une fois qu'il en a trouvé un.
Est-il possible de limiter sed à une seule modification ? Si oui comment svp ?

Exemple :
$cat bob1.txt
BATEAU
$cat bob2.txt
BATEAU


$sed -i 's/BATEAU/MAISON/' *.*


$cat bob1.txt
MAISON
$cat bob2.txt
MAISON


Or, je recherche à avoir ce type de résultat :

$cat bob1.txt
MAISON
$cat bob2.txt
BATEAU


Sachant que je ne connais pas dans quel fichier est le mot BATEAU que je veux modifier.
Configuration: Linux
Firefox 3.0.7

8 réponses

  1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Salut,

    Avec l'option "-s" de sed et la commande "q" (quitter) c'est possible. Extrait de la FAQ sur SED :
    -s, --separate
    
        * Si plusieurs fichiers sont fournis en entrée, les traiter un à un plutôt que 
          comme une seule et même page


    :
    [rep]$ grep -H 'BATEAU' fich*
    fich1.txt:BATEAU
    fich2.txt:BATEAU
    fich3.txt:BATEAU
    fich4.txt:BATEAU
    fich5.txt:BATEAU
    
    [rep]$ sed -s -i 's/BATEAU/MAISON/;q' fich*
    
    [rep]$ grep -EH '(BATEAU|MAISON)' fich*
    fich1.txt:MAISON
    fich2.txt:BATEAU
    fich3.txt:BATEAU
    fich4.txt:BATEAU
    fich5.txt:BATEAU
    
    [rep]$ 
    ;-))
    1
  2. bkrqpzef Messages postés 213 Statut Membre 5
     
    Super !
    Oui changer les séparateurs !!!! C'est une habitude que je dois prendre :p
    Merci pour la leçon, tout fonctionne.
    1
    1. m4ni4k
       
      En réalité, le tiens pouvais également fonctionner, si tu n'avais pas distraitement glisser un "/" de trop tout à la fin après ton "}"

      Ta syntaxe était certe un peu bordélique mais fonctionnait également, la preuve:

      echo GOOGLE | sed '/GOOGLE/ {s//<a href="http:\/\/www\.google\.fr\/google\/index\.html">Google<\/a>/;q}'
      0
      1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898 > m4ni4k
         
        ;-))
        0
    2. m4ni4k
       
      Un conseil, commence par lire les messages d'erreur, ils sont parfois particulièrement instructifs

      sed: -e expression n°1, caractère 85: caractères inutiles après la commande

      te mettait clairement le nez dans ta merdouille
      ;)
      0
  3. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    En y réfléchissant bien, l'option "-s" n'est pas nécessaire, et cette syntaxe serait plus appropriée :
    sed -i '/BATEAU/ {s//MAISON/;q}' fich*
    ;-))
    0
  4. bkrqpzef Messages postés 213 Statut Membre 5
     
    Pffiiioou,
    c'est exactement ce que je cherchais.
    sed -i '/BATEAU/ {s//MAISON/;q}' fich*

    Même si je ne comprend pas cette ligne. :p
    Je vais l'étudier d'un peu plus près. Merci !!!
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Par défaut lorsqu'on donne plusieurs fichiers en entrée à sed, ils sont vus comme un seul et unique fichier (d'où ma confusion avec l'option "-s", je pensais le contraire). A partir de là, il suffit d'employer la commande "q" (quitter) qui comme son nom l'indique, quitte le script dès que la condition est trouvée, donc dès que la 1ère substitution a eu lieu...

    En ce qui concerne la syntaxe : /BATEAU/ {s//MAISON/}

    /BATEAU/
    c'est le motif à rechercher

    s//MAISON/
    Pas la peine de répéter le motif vu que c'est celui-là même qu'on veut remplacer, donc on utilise la syntaxe s// qui correspond à s/BATEAU/

    Le tout entre accolades pour grouper les commandes (s et q) et signifier qu'elles ne doivent être appliquées qu'au motif fourni...
    0
  7. bkrqpzef Messages postés 213 Statut Membre 5
     
    Humm,
    sed -i '/GOOGLE/ {s//<a href="http:\/\/www\.google\.fr\/google\/index\.html">Google<\/a>/;q}/' *

    me sort :
    sed: -e expression n°1, caractère 85: caractères inutiles après la commande

    Une idée ? :p
    0
  8. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Change les séparateurs de la commande "s" (/ par défaut) par des pipes (|) ou tout autre caractère ne se trouvant pas dans la chaîne de remplacement...
    [rep]$ grep -H 'GOOGLE' fich*
    fich1.txt:GOOGLE
    fich2.txt:GOOGLE
    fich3.txt:GOOGLE
    fich4.txt:GOOGLE
    fich5.txt:GOOGLE
    
    [rep]$ sed -i '/GOOGLE/ {s||<a href="http://www.google.fr/google/index.html">Google</a>|;q}' fich*
    
    [rep]$ grep -EHi 'google' fich*
    fich1.txt:<a href="http://www.google.fr/google/index.html">Google</a>
    fich2.txt:GOOGLE
    fich3.txt:GOOGLE
    fich4.txt:GOOGLE
    fich5.txt:GOOGLE
    [rep]$  
    0
  9. bkrqpzef Messages postés 213 Statut Membre 5
     
    Ouaik :D
    Mais jipicy a accidentellement résolu un autre de mes problème avec ses conseils.
    J'utilise un appel system() en langage c pour la commande sed :
    Ce qu'il me fait un truc de fou du genre
    system("sed -i 's/\\//\\\\\\//g' *");

    Pour remplacer / par \ et /. :D
    J'ai pu du coup rendre mon code un peu plus lisible.
    Merchi à vous !
    0