Forum Programmation.shell les regex sed dingue comme ce n'est pas facile...

Posté par .
Tags :
2
25
mai
2011

bonjour,

je veux passer un flux de texte dans divers pipes pour le transformer à l'aide de sed. Ça fait plus de 3/4 d'heure que je lutte avec ça.

J'ai :

du texte et puis à la fin de la ligne, un numéro par exemple 42

je veux obtenir :

du texte et puis à la fin de la ligne, un numéro par exemple [[42 42]]

Dans l'idéal, toutes les lignes qui finissent par un nombre auraient ce nombre transformé en

[[nb nb]]

Or, à la 1ème tentative :

cat $(DOCUMENT).txt | sed -e "s/\(\d+\)$/[[ ]]/g" > $(DOCUMENT)_export.tw 

j'obtiens :

sed: -e expression n°1, caractère 20: commande `s' inachevée

J'ai essayé avec ([0-9]*) à la place de (d+), même message, avec n ou r à la place de $, pas d'erreur mais ça ne fait pas de transformation.

j'ai essayé également de renseigner le début de la ligne, avec un double remplacement, la portion de texte au début, puis le nombre à la fin :

mais cela dit également commande `s' inachevée

(avec ^ pour le début de ligne c'est accepté, mais pas la fin de ligne avec $)

Ce que je ne comprends pas c'est que les divers cours sur les regex indiquent que le $ est pour la fin d'une ligne.
Or man sed indique : $ Match the last line.

  • # sed, pas perl

    Posté par . Évalué à 4.

    Je n'ai pas d'erreur avec ton code. Mais ça il ne fonctionne pas. \d ressemble trop à du perl pour être honnête (PCRE?).

    ... | sed -e "s/\([0-9]\+\)$/[[\1 \1]]/g"

    • [^] # Re: sed, pas perl

      Posté par . Évalué à 2.

      ouaip, à deux petit détails près:
      - UUOC dans le message d'origine, sed sait très bien travailler directement sur des fichiers
      - le drapeau g pour appliquer à toutes les occurrences est inutile, a priori, il n'y a qu'une seule fin de ligne par ligne :)

    • [^] # Re: sed, pas perl

      Posté par . Évalué à 2.

      Il est possible d'utiliser directement perl :

       perl -pe 's/(\d+)$/[[$1 $1]/'
      

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: sed, pas perl

        Posté par . Évalué à 2.

        merci de l'idée.
        Avec

        perl -pe 's/(\d+)/[[\1 \1]]/g' 
        

        ça ne fait pas d'erreur, mais ça ne fait pas ce je veux (position en fin de ligne)

        Si je rajoute $ :

        perl -pe 's/(\d+)$/[[\1 \1]]/g'
        

        j'ai le même type d'erreur qu'avec sed :

        Substitution replacement not terminated at -e line 1.

        Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

        • [^] # Re: sed, pas perl

          Posté par . Évalué à 2.

          par contre ça fonctionne avec \n à la place de $ :

          cat $(DOCUMENT).txt  |  perl -pe 's/(\d+)\n/[[\1 \1]]/' > $(DOCUMENT)_export.tw 
          

          merci beaucoup pour l'idée de perl. En python c'était sans doute également possible (je connais surtout les regex via txt2tags, et cela utilise re, mais en une ligne ça me semble plus direct, et je n'ai pas trouvé comment le faire facilement en python)

          Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

          • [^] # Re: sed, pas perl

            Posté par . Évalué à 2.

            Je l'avais mis le "$" ^^

            Chez moi ça marche c'est bizarre essaie en enlevant l'inutile g à la fin.

            Perl comme sed peut prendre un fichier en paramètre :

            perl -pe 's/(\d+)\n/[[ ]]/' $(DOCUMENT).txt > $(DOCUMENT)_export.tw
            

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Enlarge your péniche

    Posté par (page perso) . Évalué à 3.

    J'ai lu : les raides sex dingues comme ce n'est pas facile…

    En perl : http://www.mail-archive.com/bug-coreutils@gnu.org/msg08694.html pourrait t'aider non ?
    En python, tu as le choix :
    _tu fais un split sur ton texte initial, tu reformes le texte initial avec tous les bouts sauf le dernier, qui contient le chiffre, que tu peux donc remettre en forme 42 42
    _ou bien les regex comme tu voulais le faire : regarde re.sub

    En tout cas sans sed.

    Commentaire sous licence LPRAB - http://sam.zoy.org/lprab/

  • # Et comme ça ?

    Posté par . Évalué à 3.

    $ echo "du texte et puis à la fin de la ligne, un numéro par exemple 42 56" | sed -e 's/\([0-9]*\)$/{{\1 \1}}/g'
    du texte et puis à la fin de la ligne, un numéro par exemple 42 {{56 56}}
    

    PS : Comment échappe-t-on des [[ ]] qui ne doivent pas être compris comme un lien Wikipedia dans du code ?

    Si vous n'aimez pas ce commentaire c'est qu'il est ironique.

    • [^] # Re: Et comme ça ?

      Posté par . Évalué à 2.

      merci, finalement je vais tout faire en perl, la syntaxe est plus claire.

      Et je vois que le code que j'avais mis en exemple ne passe pas, lors de la prévisualisation il me semblait pourtant avoir fait attention...

      Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

  • # Solution

    Posté par (page perso) . Évalué à 2.

    echo "du texte et puis à la fin de la ligne, un numéro par exemple 42"|sed -e "s/\([0-9]\+\)$/\[\[\1 \1\]\]/g"

    • [^] # Re: Solution

      Posté par . Évalué à 4.

      tu peux enlever le 'g' à la fin qui ne sert à rien ici, et ce n'est pas non plus nécessaire d'échapper les [ et ] dans la chaine de remplacement.

      Sinon, juste histoire de faire encore plus court, on peut aussi faire:

      echo "du texte bla bla 42"|sed -e "s/[0-9]\+$/[[& &]]/"
      

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.