Manipulation avec SED

Résolu
Bonjour,

Voici mon fichier de départ "test01.txt"

lundi le la les
lundi le la les
lundi le la les
lundi le la les

suite à la commande :

>sed '2,3s/le/LES/g' test01.txt j'obtiens :

lundi le la les
lundi LES la LES s
lundi LES la LES s
lundi le la les

Mon problème est double:

1) Comment limiter le remplacement à 1 seule occurence par ligne, est-ce possible?

2)Ici j'utilise un adressage par ligne pour la commande substitute, mais est il possible d'adresser dans une ligne ??

Du style qui modifierait test01.txt comme suit :

lundi le la les
lundi LES la les
lundi LES la les
lundi le la les

D'avance merci, bonne après-midi.
Configuration: Windows XP
Internet Explorer 6.0

15 réponses

  1. Webmaster
    1) Enlève le 'g', qui est un attribut 'global' pour toute la ligne :
    sed '2,3s/le/LES/' test01.txt


    2) A priori avec la regexp ci-dessus ça donne le résultat escompté !
    1. 1) Merci pour la solution d'une occurence par ligne!!!

      2) Concernant l'adressage dans une ligne (ex: remplacer ou effacer les caractères 15 et 16 de chaque ligne) cela semble bien fonctionner sous linux.

      Mais en fait il m'est imposé d'utiliser sed sous windows et donc je ne possède pas de possibilité de programmer des boucles.

      Sans possibilité de programmer des boucles, serais-je devant une impasse?

      Dores et déjà merci beaucoup.
      1. Modérateur
        Tu peux toujours lancer ta commande dans une commande shell (en séparant chaque ligne du script shell par des ';'). Exemple:
        cd plop ; ls
        1. Modérateur
          En faisant un truc du genre
          while read i; do echo -e "$i"; done < <(cat plop.txt)

          ... tu peux écrire une boucle en une commande shell...
          1. Bonjour j'ai une alternative mais cela coince ,

            Pour le fichier de départ "test01.txt"

            lundi le la les
            lundi le la les
            lundi le la le
            lundi le la les

            sed '2,3s/le/LES/2' test01.txt

            La commande donne :

            lundi le la les
            lundi le la LESs
            lundi le la LES
            lundi le la les

            Là où cela coince, c'est que SED remplace même le "le" de "les"...
            ???

            BAT
            1. Modérateur
              Là où cela coince, c'est que SED remplace même le "le" de "les"...
              Ben c'est normal tu le lui demandes implicitement avec le "2" en fin de commande !
              sed '2,3s/le/LES/' test01.txt 
              ;-)
          2. Modérateur
            Pour ne catcher que les "le" suivi d'un ' ' :
            sed '2,3s/le /LES/2' plop.txt

            après je ne sais pas si ça fait ce que tu veux...
            1. Modérateur
              Salut,

              ça ne marche pas, puisque tu obliges d'avoir un espace après le et ce n'est pas toujours le cas
              lami20j@debian:~/trash$ cat test01.txt
              lundi le la les
              lundi le la les
              lundi le la le
              lundi le la les
              lami20j@debian:~/trash$ sed '2,3s/le /LES/2' test01.txt
              lundi le la les
              lundi le la les
              lundi le la le
              lundi le la les


          3. Modérateur
            Salut,

            Là où cela coince, c'est que SED remplace même le "le" de "les"...
            Ben, ça ne coince pas.
            En réalité le moteur des regex n'est pas très intelligent. En revanche il est très persévérant et exhaustif. Donc ce qui coince c'est plutôt la manière dont on écrit et utilise une regex

            Dans ton cas le moteur s'en fiche complètement de ce que tu veux obtenir. Lui il cherche un le et il le remplace comme tu l'as demandé. Et comme tu n'as pas fait des demandes particulières, le moteur cherche la 2ème occurrence de le dans les lignes 2 à 3 n'importe s'il fait ou non partie d'un mot.

            Il faut spécifier au moteur que tu cherche à remplacer un
            caractère non mot suit d'un l suit d'un e suit d'un autre caractère non mot
            ou plutôt
            une assertion nulle début de mot suit d'un l suit d'un e suit d'une assertion  nulle fin de mot
            Donc il faut ancrer ton motif.
            Essaie comme ça
            lami20j@debian:~/trash$ cat test01.txt
            lundi le la les
            lundi le la les
            lundi le la le
            lundi le la les
            lami20j@debian:~/trash$ sed '2,3s/\ble\b/LES/2' test01.txt
            lundi le la les
            lundi le la les
            lundi le la LES
            lundi le la les
            lami20j@debian:~/trash$ sed '2,3s/\<le\>/LES/2' test01.txt
            lundi le la les
            lundi le la les
            lundi le la LES
            lundi le la les
            
            1. Webmaster
              Si vous ne souhaitez pas qu'il capture 'le' s'il fait partie d'un mot :

              sed '2,3s/\ble\b/LES/' test01.txt


              \b représente une limite de mot !
              1. Merci Jeff, et à tous les autres!!

                SED est vraiment puissant une fois que l'on connait les commandes et syntaxes mais malheureusement mal docummenté à priori

                Enfin, votre aide m'a beaucoup aidé

                A bientôt!
                1. Modérateur
                  Salut,

                  SED est vraiment puissant une fois que l'on connait les commandes et syntaxes

                  En effet, SED et très puissant.
                  Cependant ici il ne s'agit pas de SED mais des expressions régulières (regex).
                  Les regex ne sont pas implémentées de la même façon dans toutes les langages (awk, perl, python, java, php, etc.) et dans toutes les commandes (sed, grep etc.) qui les utilisent donc avant de les utiliser il faut consulter la doc.
                  En conclusion il faut les étudier avant de les utiliser pour éviter les résultats inattendues.

                  Il y a plein des choses à apprendre en ce qui concerne les regex. Voici une petite liste :
                  - les métacaractères
                  - les classes de caractères
                  - la gurmandise et la paresse des quantificateurs
                  - les quantificateurs possessifs
                  - la capture et les parenthèses non-capturantes
                  - les références arrières
                  - le groupement atomique
                  - les assertions de largeur nulle ( les ancrages ) et non-nulle
                  - les alternatives
                  - les test avant et arrières (positives ou négatives)
                  - les modificateurs de regex
                  etc.

                  En fait les regex c'est un mini langage qui a ses métacarctères qu'il faut les connaître.
                  C'est aussi très important de connaitre la mécanique des regex ( les moteurs NFA et DFA)

                  Tous ces langages partagent un même moteur, de type NFA (Nondeterministic Finite Automation). MySQL, awk et egrep, par contre, utilisent un autre type de moteur (DFA - Deterministic Finite Automation) plus simple, moins puissant mais plus rapide pour les cas (très) simples, voir simplistes ("Talking about DFA matching is very boring!" Jeffrey Friedl).


                  En bref, les regex sont très puissantes.
                  Quand vous aurez appris les expressions régulières, vous vous rendrez compte qu'elles constituent une partie inestimable de votre boîte à outils... by Jeffrey E.F. Friedl - Maîtrise des expressions régulières
                  --
                  lami20j