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!
A voir également:

7 réponses

jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
Malekal_morte- Messages postés 180304 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   24 685
 
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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
Malekal_morte- Messages postés 180304 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   24 685
 
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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
Ajpg
 
si grep est compilé avec support pcre :
grep -Po '(?<=")[^"]+(?=")' fichier.txt
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
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
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
jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 896
 
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
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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
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
Malekal_morte- Messages postés 180304 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   24 685
 
Fais avec while.
C'est mieux pour lire ligne par ligne.
0
lami20j Messages postés 21331 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 570
 
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