Extraire plusieurs sous-chaine dans une ligne

Résolu
Kai -  
 Kai -
Bonjour,

Je dois récupérer toute les chaines comprise entre _(" et ") -gettext pour ceux qui connaissent.
J'utilise actuellement sed, j'ai essayé avec grep également mais rien à faire. Tous les exemples que j'ai trouvé fonctionnent si il y a une occurrence du motif PAR lignes...

***Voici un fichier d'exemple (fichier.txt):
echo("Voici une "._("phrase sans erreur"). " et "._("sans suite").". "._("Ceci est un exemple") );

A chaque fois que je tente quelque chose, SED me récupère que la dernière occurence...
***commande :
$> sed -e 's/.*_("\(.*\)").*/\1/' fichier.txt
Résultat : Ceci est un exemple

J'ai également essayé de mettre ma commande dans une boucle FOR mais il me décompose ma phrase en :
Ceci
est
un
exemple


Si vous avez des idées : je suis preneur ! Et merci d'avance!

7 réponses

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

    $ echo $A
    echo("Voici une "._("phrase sans erreur"). " et "._("sans suite").". "._("Ceci est un exemple") );
    
    $ echo $A | egrep -o '_\("[^"]*"\)' | sed 's/_("\|")//g'
    phrase sans erreur
    sans suite
    Ceci est un exemple
    
    $

    ;-))
    3
  2. Malekal_morte- Messages postés 178136 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   24 712
     
    Salut,

    tu peux le faire avec grep, si j'ai bien compris ce que tu voulais :/

    malekalmorte@neptune:/tmp$ cat pouet
    echo("Voici une "._("phrase sans erreur"). " et "._("sans suite").". "._("Ceci est un exemple") );
    malekalmorte@neptune:/tmp$ cat pouet|grep -Eoi "\(\"([a-z]| )+\"\)"
    ("phrase sans erreur")
    ("sans suite")
    ("Ceci est un exemple")


    Après faut virer les (" et "), si tu n'en veux pas.

    Les hommes réunissent tous les erreurs de leur vie et créent un monstre qu'il appelle destin.
    1
    1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
       
      Salut,

      On peut faire grep motif fichier , cat n'est pas obligatoire
      Sinon, on peut aussi simplifier la regex ;-)

      :~$ cat pouet|grep -Eoi "\(\"([a-z]| )+\"\)"                      
      ("phrase sans erreur")   
      ("sans suite")   
      ("Ceci est un exemple")   
      :~$ grep -Eoi "\(\"([a-z]| )+\"\)" pouet   
      ("phrase sans erreur")   
      ("sans suite")   
      ("Ceci est un exemple")   
      :~$ grep -Eoi "\(\"(\w| )+\"\)" pouet   
      ("phrase sans erreur")   
      ("sans suite")   
      ("Ceci est un exemple")   
      :~$ grep -Eoi '\("([^"]| )+"\)' pouet   
      ("phrase sans erreur")   
      ("sans suite")   
      ("Ceci est un exemple")
      0
    2. Malekal_morte- Messages postés 178136 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   24 712
       
      On peut faire grep motif fichier , cat n'est pas obligatoire

      Je sais bien mais c'est une sale habitude, pis j'aime les pipes :/
      0
  3. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Re,

    Sinon avec les tests avant/arrière

    ~$ perl -ne 'while(/(?<=\(")([^"]+)(?="\))/g){print "$1\n"}' pouet 
    phrase sans erreur 
    sans suite 
    Ceci est un exemple


    GNU/Linux:Linux is Not Ubuntu! Quel linux choisir ne veut pas dire votre Distribution préférée,
    106485010510997108
    1
  4. Ajpg
     
    si grep est compilé avec support pcre :
    grep -Po '(?<=")[^"]+(?=")' fichier.txt
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Re,

    Oui, bien sûr ;-)
    Toutefois il faut tenir compte (dans son exemple) que le teste avant c'est sur (" et le teste arrière sur ") ce qui donne
    lami20j@debian-acer:~$ grep -Po '(?<=")[^"]+(?=")' pouet 
    Voici une 
    ._(
    phrase sans erreur
    ). 
     et 
    ._(
    sans suite
    ).
    . 
    ._(
    Ceci est un exemple
    lami20j@debian-acer:~$ grep -Po '(?<=\(")[^"]+(?="\))' pouet 
    phrase sans erreur
    sans suite
    Ceci est un exemple

    0
  7. Ajpg
     
    Exact, je n'avais pas fait attention.

    Une autre syntaxe en perl, pour le même résultat :
    perl -nle 'print for /(?<=\(")([^"]+)(?="\))/g' fichier.txt
    0
  8. Kai
     
    Bonjour,

    Merci à tous car la plupart de vos solutions fonctionnent dans mon script shell!!

    A lami20j : peut tu m'expliquer le détail de ta reg expr stp?
    (?<=\(")[^"]+(?="\))

    A jipicy : Pareillement. Avec egrep tu trouve la ligne et avec sed les chaines exactement comprise entre _(" et ") ??
    egrep -o '_\("[^"]*"\)' | sed 's/_("\|")//g'

    Merci encore et bonne journée!
    0
    1. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
       
      Re-

      egrep -o '_\("[^"]*"\)' ne récupère que chaque expression commençant par _(" et tout ce qui suit jusqu'au prochain ".

      sed 's/_("\|")//g' supprime le superflu, à savoir les _(" du début et les ") de fin...
      0
    2. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
       
      Salut,

      (?<=\(")[^"]+(?="\))

      (?<=\(")

      Il s'agit d'un test arrière (?<=MOTIF)
      Le MOTIF dans notre cas c'est une parenthèse ouvrante suivie par guillemets. \("
      On met un backslash avant la parenthèse puisque dans les regex les parenthèses ont le rôle de capture.


      (?="\))

      Il s'agit d'un test avant (?=MOTIF)
      Le MOTIF dans notre cas c'est guillemets suivie d'une parenthèse fermante. "\)
      On met un backslash avant la parenthèse puisque dans les regex les parenthèses ont le rôle de capture.

      [^"]+

      [^"] - c'est une classe de caractères qui permet de reconnaître n'importe quel caractère sauf les guillemets

      + - c'est un quantificateur qui veut dire une fois ou n'importe combien des fois.

      Avec la regex on regarde en arrière pour voir si on a une parenthèse ouvrante suivi de guillemets et devant pour voir s'il y a guillemets suivis d'une parenthèse fermante.
      Les tests avant ne consomment pas de textes. Ils trouvent juste une position avant ou arrière.

      Dans un langage plus accessible pour nous les humains c'est
      Cherche n'importe quelle chaîne de caractères qui ne contienne pas des guillemets et qui se trouve entre (" et ")
      0
    3. Kai
       
      Ok, merci !

      Le truc c'est que j'ai besoin de chaque chaine trouvée pour vérifier si elles sont présentes dans un autre fichier...
      Et quand je veux parcourir mon résultat , voila ce que ca donne:

      $> for chaine in 'echo 'echo("Voici une "._("phrase sans erreur"). " et "._("sans suite").". "._("Ceci est un exemple") );' | egrep -o '_\("[^"]*"\)' | sed 's/_("\|")//g''; do echo "chaine :"$chaine; done
      chaine :phrase
      chaine :sans
      chaine :erreur
      chaine :sans
      chaine :suite
      chaine :Ceci
      chaine :est
      chaine :un
      chaine :exemple



      Comment dire au FOR de ne pas casser mes lignes pour récupérer :
      chaine :phrase sans erreur
      chaine :sans suite
      chaine :Ceci est un exemple


      ???
      0
    4. Malekal_morte- Messages postés 178136 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   24 712
       
      Fais avec while.
      C'est mieux pour lire ligne par ligne.
      0
    5. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
       
      Re,

      Ou avec un tr

      $ for chaine in $(echo '("Voici une "._("phrase sans erreur"). " et "._("sans suite").". "._("Ceci est un exemple") )'| egrep -o '_\("[^"]*"\)' | sed 's/_("\|")//g'|tr ' ' _); do echo "chaine : ${chaine//_/ }"; done
      chaine : phrase sans erreur
      chaine : sans suite
      chaine : Ceci est un exemple
      0