2 votes

Problème de Regex : Impossible de faire correspondre un motif de longueur variable

J'ai un problème avec les expressions rationnelles, en utilisant preg_match_all(), pour faire correspondre quelque chose de longueur variable.

Ce que j'essaie de faire correspondre, c'est l'état du trafic après le mot "congestion". J'ai trouvé ce modèle de regex :

Congestion\s*:\s*(?P<congestion>.*)

Il extrairait cependant la première instance jusqu'à la fin du sujet entier, puisque .* correspondrait à tout. Mais ce n'est pas ce que je veux, j'aimerais qu'elle corresponde séparément à 3 instances.

Maintenant, puisque les mots derrière Congestion peuvent être de longueur variable, je ne peux pas vraiment prédire combien de mots et d'espaces il y a entre eux pour arriver à un critère plus strict. \w * \s * \w * match etc.

Des indices sur la façon dont je peux procéder à partir de là ?

Highway : Highway 26
Datetime : 18-Oct-2010 05:18 PM
Congestion : Traffic is slow from Smith St to Alice Springs St

Highway : Princes Highway
Datetime : 18-Oct-2010 05:18 PM
Congestion : Traffic is slow at the Flinders St / Elizabeth St intersection

Highway : Eastern Freeway
Datetime : 18-Oct-2010 05:19 PM
Congestion : Traffic is slow from Prince St to Queen St

MODIFIER POUR PLUS DE CLARTÉ

Ces textes très joliment formatés sont en fait reçus via un courrier électronique html très mal formaté. Il contient des sauts de ligne aléatoires ici et là, par exemple "Congestion : Trafic". \n est lent de Prince \nSt à Queen St".

Donc, pendant le traitement des courriels, j'ai enlevé tous les codes html et les sauts de ligne aléatoires, et json_encode() les a transformés en une très longue chaîne d'une seule ligne sans saut de ligne...

4voto

Konrad Rudolph Points 231505

En général, la correspondance des expressions rationnelles est basée sur les lignes. Regex suppose que votre chaîne est une ligne unique. Vous pouvez utiliser la fonction " m " ( PCRE_MULTILINE ) drapeau pour changer ce comportement. Ensuite, vous pouvez dire à PHP de n'aller qu'à la fin de la ligne :

preg_match('/^Congestion\s*:\s*(?P<congestion>.*)$/m', $subject, $matches);

Il y a deux choses à noter : premièrement, le modèle a été modifié pour inclure le début de ligne ( ^ ) et de fin de ligne ( $ ). Deuxièmement, le motif porte maintenant la mention m modificateur.

2voto

Amarghosh Points 33957
Congestion\s*:\s*Traffic is\s*(?P<c1>[^\n]*)\s*from\s*(?P<c2>[^\n]*)\s*to\s*(?P<c3>[^\n]*)$

2voto

Uphill_ What '1 Points 673

Vous pouvez essayer une correspondance minimale :

Congestion\s*:\s*(?P<congestion>.*?)

Cela aurait pour résultat de renvoyer zéro caractère dans le groupe nommé "congestion", à moins que vous ne puissiez faire correspondre quelque chose immédiatement après la chaîne "congestion".

Cela pourrait donc être corrigé si "Highway" démarrait toujours les enregistrements des conditions de circulation :

Congestion\s*:\s*(?P<congestion>.*?)Highway\s*:

Si cela fonctionne (je ne l'ai pas vérifié), alors les premiers enregistrements sont appariés mais pas le dernier ! Cela pourrait être facilement corrigé en ajoutant le texte 'Highway :' à la fin de la chaîne de saisie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X