Forum Programmation.shell Découpe d'une chaine de caractère

Posté par  .
Étiquettes : aucune
0
2
août
2011

Bonjour,

Je parcours un fichier et à chaque ligne il faut que je découpe la chaine de caractère rencontrée (en me basant sur "_") en ne gardant que l'avant dernière occurrence.

Voila les datas du fichiers :

TOTO1_TOTO2_pub (soit TOTO2)
TUTU1_TUTU2_TUTU3_pub (soit TUTU3)
TATA1_TATA2_pub (soit TATA2)
TOTO1_TOTO2_TOTO3_TOTO4_pub (soit TOTO4)
...

La longueur des chaines varient toujours, le seul point commun à chacune étant "_pub".

J'ai essayé avec du sed et des regexp mais je ne maitrise pas vraiment :s

Merci d'avance!

  • # Shell

    Posté par  . Évalué à 3.

    Salut,

    tu peux passer par du shell pour ce genre de manipulation, en bash par exemple :

    while read a ;do a=${a%_*}; echo ${a##*_} ; done < ton_fichier
    

    Plus court en zsh :

    while read a ; do echo ${${a%_*}##*_} ; done < ton_fichier
    
    • [^] # Re: Shell

      Posté par  . Évalué à 3.

      Pas mieux. J'avais :

      #!/bin/zsh
      cat $1 | while read line
      do
      	a=( ${(z)line//_/ } )
      	print $a[-2]
      done
      
      • [^] # Re: Shell

        Posté par  . Évalué à 2.

        On peut en effet partir sur un split et sortir l'avant dernier élément comme tu as fais :

        while read a ; do print ${${(s:_:)a}[-2]} ; done < ton_fichier
        
  • # un debut

    Posté par  . Évalué à 2.

    couper selon le motif :

    cut -d '_' -fX fichier

    avec X le numero de l'element à afficher apres avoir decouper la chaine à chaque motif de '_'

    par contre il faut trouver la longueur de ce qui est renvoyé pour recuperer l'indice du dernier et n'afficher que le dernier

    une regexp serait de chercher TOUT ce qui se trouve entre _ et le motif de fin

  • # sed

    Posté par  . Évalué à 3.

    Avec sed je dirais :
    sed "s/^.([^])_pub$/\1/"

    Sinon avec awk ça doit être faisable également (je connais pas spécialement ...)
    Je me demande si c'est possible de le faire avec cut

    • [^] # Re: sed

      Posté par  . Évalué à 6.

      Sinon avec awk ça doit être faisable également (je connais pas spécialement ...)

      gawk 'BEGIN { FS = "_"; } { print $(NF-1); }'

      Hop,
      Moi.

      • [^] # Re: sed

        Posté par  . Évalué à 5.

        Et on peut faire encore un peu plus court en remplaçant le bloc BEGIN par l'option -F

        gawk -F _ '{print $(NF-1)}'

  • # version sed

    Posté par  . Évalué à 3.

    sed -e "s/^.*_\([^_]*\)_pub$/\1/"

    • [^] # Re: version sed

      Posté par  . Évalué à 2.

      j'ai trouvé exactement la même, par contre je ne comprends pas du tout pourquoi celle ci
      sed "s/^.([^_])_pub$/\1/"
      ne fonctionne pas ! une idée ?

    • [^] # Re: version sed

      Posté par  . Évalué à 2.

      avec la balise pour le code :

      sed -e "s/^.*\([^_]*\)_pub$//"
      

      devrait fonctionner il me semble, je ne comprends pas pourquoi il ne sort rien.
      • [^] # Re: version sed

        Posté par  . Évalué à 3.

        sed -e "s/^.*\([^_]*\)_pub$//"
                                   ^^
        

        je ne comprends pas pourquoi il ne sort rien.

        L'expression de remplacement est vide. Regarde le commentaire parent, il utilise '\1' pour remplacer par le contenu dans les parenthèses.

        Hop,
        Moi.

      • [^] # Re: version sed

        Posté par  . Évalué à 2.

        je suppose que le \1 a été bouffé par templeet
        par défaut les ?,,+ sont greedy -gourmand- donc le premier . contient tout et la deuxième partie rien pour contrer cet effet, il suffit d'en mettre un

        ^.*_\([^_]*\)_pub$
        

        une autre solution est d'utiliser perl qui à un méchanisme de non greedy; ce qui donnerai

        s/^.*?([^_]*)_pub$/$1/;
        

        Il ne faut pas décorner les boeufs avant d'avoir semé le vent

  • # explication regexp

    Posté par  . Évalué à 1.

    Le dernier sed fonctionne bien merci !! (l'avant dernier proposé non :/)

    Pourrais-je avoir une explication de l'expression reguliere ? Merci! :)

    • [^] # Re: explication regexp

      Posté par  . Évalué à 2.

      il manque une etoile sur l'avant dernier en fait ... j'ai un peu oublié la balise code

      ^ début de chaîne
      
      .* n'importe quel caractère 0 ou n fois
      _
      
      \( début de capture d'expression
      
      [^_]* Tout caractère sauf _ 0 ou n fois
      
      \) fin de capture
      
      _pub
      
      $ fin de chaîne    
      

      Je te conseil le site http://www.expreg.com/

Suivre le flux des commentaires

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