Regexp capture de données

Messages postés
3708
Date d'inscription
lundi 5 juillet 2004
Statut
Membre
Dernière intervention
27 avril 2012
- - Dernière réponse : kohntark
Messages postés
3708
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 -
Afficher la suite 

11 réponses

Messages postés
6069
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
21
0
Merci
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
Commenter la réponse de nhervagault
Messages postés
1305
Date d'inscription
mardi 9 novembre 2004
Statut
Membre
Dernière intervention
21 mai 2015
0
Merci
ç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°
Commenter la réponse de kankrelune
Messages postés
3708
Date d'inscription
lundi 5 juillet 2004
Statut
Membre
Dernière intervention
27 avril 2012
21
0
Merci
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 -
Commenter la réponse de kohntark
Messages postés
3708
Date d'inscription
lundi 5 juillet 2004
Statut
Membre
Dernière intervention
27 avril 2012
21
0
Merci
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 -
Commenter la réponse de kohntark
Messages postés
6069
Date d'inscription
dimanche 13 avril 2003
Statut
Modérateur
Dernière intervention
15 juillet 2011
21
0
Merci
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
Commenter la réponse de nhervagault
Messages postés
1305
Date d'inscription
mardi 9 novembre 2004
Statut
Membre
Dernière intervention
21 mai 2015
0
Merci
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... .. .
Commenter la réponse de kankrelune
Messages postés
3708
Date d'inscription
lundi 5 juillet 2004
Statut
Membre
Dernière intervention
27 avril 2012
21
0
Merci
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 -
Commenter la réponse de kohntark
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
22 août 2018
54
0
Merci
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...
Commenter la réponse de Renfield
Messages postés
3708
Date d'inscription
lundi 5 juillet 2004
Statut
Membre
Dernière intervention
27 avril 2012
21
0
Merci
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 -
Commenter la réponse de kohntark
Messages postés
17308
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
22 août 2018
54
0
Merci
(\d+) pm

je vois pas pourquoi ça séléctionne le 96 du renard rusé...
Commenter la réponse de Renfield
Messages postés
3708
Date d'inscription
lundi 5 juillet 2004
Statut
Membre
Dernière intervention
27 avril 2012
21
0
Merci
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 -
Commenter la réponse de kohntark