Regexp capture de données

kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 - 23 juin 2009 à 21:52
kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 - 27 juin 2009 à 16:30
Salut,

En cette fin de journée fatigante je galère un peu.
Voici la trame que j'essaie de parser :
tototata - 140 db - excellent - truc-bidule - bidule machin


 
140 db, étonnant, 8 pm, theodore


Données bidule, truc (jazz)






en noir : ce que je cherche à capturer (changeant, forcemment)

en bleu : les parties qui ne changent jamais

en rouge : ce qui fait que je vais devenir chauve plus vite que prévu


A savoir qu'il peut y avoir des retours à la ligne et autres caractères
"blancs" aléatoires entre la cloture d'une balise et la suivante.


Le problème :

Les données en rouge peuvent prendre les formes suivantes :
140 db, étonnant, 8 pm, theodore

140 db, 8 pm, theodore

140 db, étonnant, 8 pm

140 db, étonnant, machinchose, 8 pm, theodore

8 pm


etc ... en fait le nombre de données, séparées par des virgules (et qui
peuvent contenir des chiffres, des caractères spéciaux etc ... mais
jamais de virgule), peut changer, avant comme après le 8 pm que je
cherche à capturer.

Par ailleurs, pour faciliter grandement la chose, le 8 pm (qui peut également être 208 pm, 102 pm) n'est pas toujours présent.


Pour ceux qui suivent encore après cette magnifique tentative d'explication :

je cherche à trouver le nombre de pm (8 pm) que contient la chaîne, et
savoir également, de façon fiable (of course) si elle n'est pas
présente.


Les autres données (en noir) ne me pose pas de pb, de même qu'isoler la
ligne rouge et appliquer un second traitement dessus pour sortir le 8
pm (mais je souhaiterai le faire en 1 seule regex)


... en espérant m'être bien expliqué (pas gagné, je sais )
Merci à vous.


Cordialement,

Kohntark -

11 réponses

nhervagault Messages postés 6063 Date d'inscription dimanche 13 avril 2003 Statut Membre Dernière intervention 15 juillet 2011 37
23 juin 2009 à 22:24
Salut,

Je vais tenter

.*?(?<Num>\d pm).*?

en mode singleline

avec 140 db, &eacute;tonnant, 8 pm, theodore

140 db, 8 pm, theodore

140 db, &eacute;tonnant, 8 pm

140 db, &eacute;tonnant, machinchose, 8 pm, theodore

8 pm

Je touve les 5  -- 8 pm

en espérant avoir compris le problème
0
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
24 juin 2009 à 11:19
ça passe pas... il faudrait une * avec le \d car à priori la valeur numérique peut être supérieur à 9 et ça bloque s'il y a des Xpm dans des mots... sur...

140 db, ligne 1, 8 pm, 10pm theodore

db, 2, pm, ligne 2

140 db, étonnant, ligne 4, 100pm, theodore

140db, ligne 40 pm

opsus20pmjkl, ligne 3, 12 pm

dbligne12pmplm

m228 pm fgh
étonnant, ligne 4, 29 pm, theodore

140 db, 140 pmdb,ligne 3, 46pm

10 pm


ca match...

array (
0 => '8 pm',
1 => '0 pm',
2 => '2 pm',
3 => '8 pm',
4 => '0 pm',
5 => '0 pm',
),

Perso je dirais...

/\b([0-9]+\s*pm)\b/i

ça match correctement le seul pb peut être avec la ponctuation... à voir... .. .

@ tchaOo°
0
kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 30
25 juin 2009 à 22:47
Merci pour vos réponses.
Je n'ai pas eu beaucoup de temps ces derniers jours mais j'ai tout de même retravaillé un peu le sujet en tenant compte de vos propositions, sans succès.

C'est particulièrement galère d'exposer ce genre de problème , je tente donc d'apporter quelques compléments et précisions :
tototata - 140 db - excellent - truc-bidule - bidule machin

 
40 db, &eacute;tonnant, 800 pm, theodore

Données bidule, truc (jazz)



En simplifiant :
[a]\s-\s[b]

[c]

Données\s[d]\s(jazz)

En bleu : les données qui ne changent jamais
Le nombre de \r, \n et autres caractères "blanc" peuvent être variable entre la fin d'une balise HTML et la suivante (ou plus précisément entre : </h3> et ,
et

)

[a] : chaîne de caractères toujours présente, alphanumérique (char '-' et '_' pouvant être présent, mais en principe pas de ',' ni de ' ')
[b] : plusieurs données alphanumériques avec char spéciaux possibles, séparées par '\s-\s'
'40 db' ne peut avoir que 2 chiffres (et pas 3)
exemples :
40 db - excellent - truc-bidule - bidule machin
ou
80 db
ou
40 db - nul - bidule - truc muche
etc ...
[d] : idem à [b], mais séparées par ',\s' sans aucun chiffre présent
[c] : (== le problème)
chaîne séparée par des ',\s', avec un nombre de données aléatoire.
exemples :
140 db, &eacute;tonnant, 800 pm, theodore
14 db, banal, 100 pm
18 db
39 db, 186 pm
etc ...

Je cherche à capturer le 800 pm, qui n'est pas forcement présent. Dans ce cas la regex doit retourner tous les autres résultats et ne pas échouer.
Le 40 db semble toujours être présent.
Le 8 pm annoncé initialement est toujours sur 3 digits.

brillant exposé n'est ce pas ? ( on ne se moque pas !!!)

Voilà ce que j'ai pondu hier matin :
`(.*)\s?-\s?(.*) db\s?-\s?.*\s-\s.*\s?-?\s?.*
\s*class="mtruc" id="m2truc">\s*(\d{2}\sdb)(\D*)((\d{3})\s(pm))?.*
\s*Données\s*(.*),\s*(.*)\s\(jazz\)
`

En fait je me base sur l'existence systématique de 140 db et sur le fait que les données suivantes ne peuvent pas contenir de chiffres.
Cette regex semble donner satisfaction dans l'absolu, mais je ne suis pas certain que la chaîne entre 140 db et 800 pm ne contienne jamais de [0-9]
Je suis sur qu'elle est optimisable, mais sur le coup j'ai du mal

Encore merci pour vos réponses.

Cordialement,

Kohntark -
0
kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 30
25 juin 2009 à 22:51
140 db, &eacute;tonnant,
800 pm, theodore
=>
en fait




40 db, &eacute;tonnant,
800 pm, theodore



puisque 40 db est toujours sur 2 digits.

Kohntark -
0

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

Posez votre question
nhervagault Messages postés 6063 Date d'inscription dimanche 13 avril 2003 Statut Membre Dernière intervention 15 juillet 2011 37
25 juin 2009 à 23:55
Cet expression passe en regexp .net

Jeu d'essai

tototata - 140 db - excellent - truc-bidule - bidule machin

40 db, étonnant, 800 pm, theodore

Données bidule, truc (jazz)




Expression
<h3.*?>(?.*?)\s-\s(?.*?)<\/h3>\s(?<c>.*?)

Données (?<d>.*?)\s\(jazz\)

<\/p>


J'ai pas tenu compte des types et des pattern pour les captures
a, b, c, d

Il faut remplacé les .*? par les bons patterns

Option regexp utilisée singleline
0
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
26 juin 2009 à 00:58
Bah moi en fait plus t'explique moins je comprend... lol... .. .

Tu veux capturer tous les pm et uniquement les pm
Tu veux capturer tout ce que tu as décrit en noir
Tu veux capturer les pm et ce qu'il y a en noir si pas de pm

j'ai beau relire... je pige rien... lol... .. .

@ tchaOo°

ps: si c'est les pm que tu veux je l'ai posté plus haut...

/\b([0-9]+ *pm)\b/i

ou...

/\b([0-9]+ pm)\b/i

ça dépend si tu veux un seul espace ou pas avant le pm... pour le reste je regarderais ça tout a l'heure ou demain... .. .
0
kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 30
26 juin 2009 à 08:31
je m'explique comme un manche, c'est ça ?

La chaîne complète, qui fait partie d'une longue page :

[tototata] - [140] db - excellent - truc-bidule - bidule machin

140 db, &eacute;tonnant, [80] pm, theodore

Données [bidule], [truc](jazz)



en bleu : les données qui ne changent jamais et qui sont toujours présente
en gris : les données qui changent mais qui sont toujours présentes
en rouge : les données qui changent et qui peuvent être absentes
entre [] : ce que je cherche à matcher
(je ne match plus le excellent comme dit dans mon premier post, et ne prend plus le 'pm' de '80 pm')

Cette chaine peut donc prendre les formes suivantes :

tototata - 140 db - truc_bide - bidule machine

140 db, 20 pm, theodore

Données bidule, trucmuche (jazz)



OU

titata - 140 db

140 db, zorro, bernardo, 84 pm, theodore

Données bidule, machine (jazz)



OU

titata

140 db, zorro, bernadette

Données bidule, machine (jazz)



OU

titata - 140 db

140 db, 84 pm, theodore, papamaman

Données bidule, machinette (jazz)



...

En simplifiant :
[a]\s-\s[b]

[c]

Données\s[d]\s(jazz)

[c] : (= = le problème)
chaîne séparée par des ',\s', avec un nombre de données aléatoire.
exemples :
[c] peut prendre les formes suivantes :
140 db, &eacute;tonnant, 800 pm, theodore
ou
14 db, banal, 100 pm
ou
18 db
ou
39 db, 186 pm
etc ...

La regex que j'ai écrit marche bien :
`(.*)\s?-\s?(.*) db\s?-\s?.*\s-\s.*\s?-?\s?.*
\s*class ="mtruc" id= "m2truc">\s*(\d{2}\sdb)(\D*)((\d{3})\s(pm))?.*
\s*Données\s*(.*),\s*(.*)\s\(jazz\)
`

Par contre si je tombe sur des digits avant le ((\d{3})\s(pm)) et après le (\d{2}\sdb) elle ne fonctionnera plus.
Par exemple une chaîne de ce type :

titata - 140 db

140 db, zorro_ 96 , bernardo, 84 pm, theodore

Données bidule, machine (jazz)



Je n'ai pas encore rencontré ce pb mais il est probable que ce type de chaîne existe.

@[../auteur/NHERVAGAULT/84425.aspx nhervagault]
Il faut remplacé les .*? par les bons patterns

=>
mon problème est là justement (pour le c uniquement)

Bonne journée à vous,

Kohntark -
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
26 juin 2009 à 14:15
un 'or', et ca repart...

(.*?)(?:(?:.*?\b(\d+) db\b)|)[\s\S]+?\s+(\d+) db(?:(?:.*?, (\d+) pm\b)|).*?
\s+Données +(.+?), +(.+?)\b

voir ici le:

(?:(?:.*?, (\d+) pm\b)|)

qui permet d'extraire le "xx pm" s'il existe...
0
kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 30
26 juin 2009 à 20:18
Salut Renfield,

Merci beaucoup pour ta réponse. Ton approche m'a pas mal apporté. J'avais déjà tenté des or mais dans une autre logique qui semble t il n'était pas la bonne. Ton analyse est bien meilleure malgré le fait que tu n'ai pas tous les éléments ... chapeau bas

Cela étant ta regex est un peu trop permissive dans mon cas de figure (chose que tu ne pouvais savoir) et elle retourne d'autres résultats de la page. Elle ne match pas le [d] de mon dernier message si celui ci contient des '-', par exemple :
140 db, zorro_96, bernardo, 84 pm, theo-dore

J'ai constaté également qu'elle "matchait" des chaînes complètes au lieu de retourner les éléments désirés.

Je l'ai donc "rapidement" modifiée afin qu'elle soit compatible avec php, moins permissive et plus rapide :
$reg = '`<h3 class="machinTruc">(.+)(?:(?:.*?\b(\d+) db\b)|)[\s\S]+?"mtruc" id="m2truc">\s+(\d{2})\sdb((?:.*?,\s(\d+)\spm\b)|).*?
\s*Données\s(.+),\s(.+)\s\(jazz\)
`';

Ce n'est pas encore parfait, mais ça règle le pb des éventuels digits entre le dn et le pm. Je re posterai une regex un peu plus optimisée rapidement.

Merci encore pour la methodologie qui était au final ce qui me manquait le plus.

Cordialement,

Kohntark -
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
27 juin 2009 à 14:59
(\d+) pm

je vois pas pourquoi ça séléctionne le 96 du renard rusé...
0
kohntark Messages postés 3705 Date d'inscription lundi 5 juillet 2004 Statut Membre Dernière intervention 27 avril 2012 30
27 juin 2009 à 16:30
Pas  le 96, mais le "theo-dore" :

"[...]si celui ci contient des '-', par exemple :
140 db, zorro_96, bernardo, 84 pm, theo-dore
"

Le 96 est en gras car j'avais fait un copié/collé d'un exemple précédent. Méa culpa, j'aurai dû le supprimer pour éviter la confusion et augmenter la taille du '-' bleu.

Cordialement,

Kohntark -
0
Rejoignez-nous