Page 1 sur 2

[..] Avoir tous les résultats avec StringRegExp

Posté : sam. 06 sept. 2008 14:12
par tolf
Bonjour,

Dans mon script j'utilise une chaîne de caractères contenant de virgules et je voudrais séparer la chaîne suivant les virgules donc pour le moment pas de problème :

Code : Tout sélectionner

StringSplit($chaine, ",")
seulement voilà je ne voudrais pas que les virgules servent de séparateur quand elles sont entre des guillemets. Je pense donc que la fonction StringRegExp est tout à fait appropriée et voici mon code :

Code : Tout sélectionner

#include <Array.au3>
$resultat = StringRegExp('salut, "bonjour, comment allez vous ?", #00ffff, 354', '[^,"]*("[^"]*")*[^,"]*', 3)
_ArrayDisplay($resultat)
Problème : la table $resultat ne contient que 'salut' alors que je voudrais qu'elle contienne :

salut
"bonjour, comment allez vous ?"
#00ffff
354


a priori, le flag 3 correspond à des résultats globaux donc comment faire ?

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : sam. 06 sept. 2008 20:43
par moutelous
Bonjour tolf,


Pour ma part je m'attends également à trouver toutes les occurrences avec le flag 3, curieux ... avec les quelques tests effectués de mon côté le global s'arrête dès le premier caractère qui ne "match" pas ...

Une petite recherche supplémentaire s'impose ...

A+

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : sam. 06 sept. 2008 21:46
par sylvanie
Bonsoir, l'expression n'est pas bien adaptée :
[^,"]*("[^"]*")*[^,"]*
salut, "bonjour, comment allez vous ?", #00ffff, 354

salut vat matcher avec [^,"]*
mais le reste de la chaîne suivant salut est : ', "bonjour, comment allez vous ?", #00ffff, 354'
et doc à cause de ', ' on s'arrête

pour rendre la recherche générique, on doit donc sélectionner :
tout ce qui ne comporte pas de , ni de "
ou
tout ce qui est de la forme "......."

ie
([^,"]+)
|
(".*")

les () sont très importantes, car elles forcent le regroupement

d'où au final :

Code : Tout sélectionner

#include <Array.au3>
$resultat = StringRegExp('salut, "bonjour, comment allez vous ?", #00ffff, 354', '([^,"]+)|(".*")', 3)
_ArrayDisplay($resultat)
cependant, une lacune dans cette dernière expression persiste : des lignes retournées vide (espaces ?) en trops, d'où un second traitement à faire après pour les éliminer en attendant de poffiner l'expression :
[0]|salut
[1]|
[2]|
[3]|"bonjour, comment allez vous ?"
[4]| #00ffff
[5]| 354

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : sam. 06 sept. 2008 22:47
par moutelous
Re ....

En fait l'expression de Tolf est la bonne à un caractère près :

Cette expression match correctement (sous autoit) :

Code : Tout sélectionner

[^,"][color=#FF0000]+[/color]("[^"]*")*[^,"]*
A+

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : sam. 06 sept. 2008 23:35
par sylvanie
bien vu,
d'ailleurs celle-ci du coups suffit :

Code : Tout sélectionner

[^,"]+("[^"]*")*

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 00:17
par moutelous
Ouaip ...

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 00:49
par Tlem
Trop fort les expressions régulières.
Je vous envie de les maitriser. :cry:

Sylvanie, un explication détaillée de la dernière solution serait très apprécié. :mrgreen:

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 13:22
par tolf
Tlem a écrit :Trop fort les expressions régulières.
Je vous envie de les maitriser. :cry:
J'ai (presque complètement) traduit le fichier texte correspondant à la fonction ici et je pense qu'il serait utile de générer le fichier html et de le mettre sur le forum.
Tlem a écrit :Sylvanie, un explication détaillée de la dernière solution serait très apprécié. :mrgreen:

Code : Tout sélectionner

[^,"]+("[^"]*")*
signifie :
- [^,"] tout caractère autre que virgule et guillemet double
- + répété 1 ou plusieurs fois
- ("[^"]*") un groupe composé d'un guillemet, puis de tout caractère autre que guillemet répété autant de fois que nécessaire, puis d'un guillemet
- * ce groupe étant répété autant de fois que nécessaire

Re: [R] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 16:33
par sylvanie
voilà une joile explication, rien à ajouter...

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 16:54
par tolf
oui mais petit problème : si je ne mets pas d'espace après la virgule aïe aïe aïe :cry: voici le résultat :

chaîne :

Code : Tout sélectionner

 'salut,"bonjour, comment allez vous ?","moi, je vais bien",#00ffff,354'
résultat :

Code : Tout sélectionner

[0]salut
[1]bonjour
[2]","
[3]moi
[4] je vais bien
[5]#00ffff
[6]354
:roll:

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 17:33
par tolf
ceci est sans doute dû au fait que le premier caractère ( [^,"] = tout caractère autre que virgule et guillemet) doit pouvoir exister en 0 fois (comme au début).
Donc en fait, je pense que le bug du début était dû au fait qu'une chaîne vide correspondait au pattern (car * peut valoir "existant 0 fois").

Donc raisonnons autrement. Le pattern est composé de [^,"] et de ("[^"]*"). Il faut faire figurer les cas de figure suivants :
- le 1er existant 0 fois et le 2ème au moins une fois (pour éviter la chaîne vide) : ("[^"]*")+
- le 1er existant 1 fois ou plus et le 2ème 0 fois : [^,"]+
- les deux existant 1 fois ou plus : [^,"]+("[^"]*")+

donc, en rassemblant les 3 par des |, ça fait le pattern suivant : (("[^"]*")+)|([^,"]+)|([^,"]+("[^"]*")+)

mais il y a des répétition dans les résultats dans ce cas :roll:

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 22:25
par Tlem
Les expressions régulières sont souvent très commode pour retrouver un résultat en très peut de ligne de code, mais parfois ce n'est pas si simple et le temps de trouver le bon Pattern on à plus vite fait de faire une fonction simple. :P

Donc comme je suis mauvais en expressions régulières :oops: , je vais proposer une alternative plutôt basique, mais fonctionnelle. 8)
► Afficher le texteDécomposition d'une chaîne
Je pense qu'avec un StringRegExpReplace pour remplacer les virgules hors "" par un | puis un StringRegExp du résultat ce serait plus simple. :lol:

A vous Tolf et Sylvanie ... :mrgreen:

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : dim. 07 sept. 2008 23:24
par moutelous
Bonjour,
Tlem a écrit :Les expressions régulières sont souvent très commode pour retrouver un résultat en très peut de ligne de code, mais parfois ce n'est pas si simple et le temps de trouver le bon Pattern on à plus vite fait de faire une fonction simple. :P
Mais si, mais si ....

Essayez donc ceci :

Code : Tout sélectionner

[^,"\s]+|("[^"]*")
:P :P

A+

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 00:06
par Tlem
Ha vi, ça fonctionne rudement bien (screugneugneu :? ) :D

Manque plus que les explications. :lol:

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 00:23
par moutelous
Tlem a écrit :Manque plus que les explications. :lol:
[^,"\s]+ : match avec tout caractère autre que , " ou forme d'espace (\s), répété 1 ou plusieurs fois
|: ou
("[^"]*") :match avec un groupe formé d'un " suivi de tout caractère répété 0 ou plusieurs fois autre qu'un guillemet et terminé par un "

Vouala

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 18:41
par sylvanie
le pb du \s est qu'il va splitter les mots entre 2 , :

exple :

Code : Tout sélectionner

$resultat = StringRegExp('salut tout le monde,"bonjour, comment allez vous ?","moi, je vais bien",#00ffff,354', '[^,"\s]+|("[^"]*")', 3)
[0]|salut
[1]|tout
[2]|le
[3]|monde
[4]|"bonjour, comment allez vous ?"
[5]|"moi, je vais bien"
[6]|#00ffff
[7]|354

Et si on l'enlève, ça marche , mais on revient à l'expression où il faut dans certains cas écrèmer les lignes "vides" en trops ...
faut voir si dans le besoins initial de Tolf, on peut être dans ce cas de figure.
il est intéressant ce cas ...

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 20:37
par moutelous
Ah ! ben NON

Une des règles majeur du REGEX est d'étudier le fichier à exploiter, je suis donc parti du postulat qu'entre les virgules il n'existe qu'un seul terme (sans espace), si virgule(s) et donc espace(s) existent, c'est une phrase , qui doit donc être mise entre guillemet ! (sinon pourquoi cette différence ?)

Dans ce sens le pattern proposé match bien avec le besoin initial de Tolf .......

Mais bon, on peut changer les règles du jeu, soyons joueur :wink: et essayons d'inclure ces espaces ...

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 21:00
par tolf
Bon j'ai opté pour la solution de Tlem qui est en fait très bien (j'avais juste un peu la flemme de faire une telle fonction au début en croyant que StringRegExp diminuerait la taille de mon code mais en fait ça me prend plus de temps :mrgreen: ).
J'ai juste un petit peu modifié le code pour que s'il y a un '|' déjà existant, il ne serve pas de séparateur :
► Afficher le texteDécomposition de chaîne modifié
Par contre, j'aimerais bien connaître la solution avec StringRegExp (car elle doit sûrement exister celle-là :evil: ) car elle doit être très intéressante.

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 21:09
par Tlem
J'ai pas trop compris la remarque de Sylvanie, car ce pattern [^,"\s]+|("[^"]*") crée bien le tableau comme le souhaite tolf :

Code : Tout sélectionner

[0] salut
[1] "bonjour, comment allez vous ?"
[2] "moi, je vais bien"
[3] #00ffff
[4] 354
et non le résultat présenté par Sylvanie. :shock:

Re: [..] Avoir tous les résultats avec StringRegExp

Posté : lun. 08 sept. 2008 21:21
par Tlem
@tolf vous pouvez vous simplifier la vie en utilisant comme séparateur une suite de symboles improbable (genre ~#~) et modifier la fonction StringSplit en mettant le flag à 1. 8)

J'ai vu ça en lisant la doc, et ça m'a permis de voir que StringSplit peut splitter une chaîne sur plusieurs caractères en même temps. :roll: