2010-12-09 7 views
2

La chaîne s est plus grande, mais je l'ai raccourcie pour simplifier.La chaîne facultative ne correspond pas dans l'expression régulière

>>> import re 
>>> s = "Blah. Tel.: 555 44 33 22." 
>>> m = re.search(r"\s*Tel\.:\s*(?P<telephone>.+?)\.", s) 
>>> m.group("telephone") 
'555 44 33 22' 

Le code ci-dessus fonctionne, mais si j'Enroulez le regex en ()? pour la rendre facultative, je ne reçois pas un téléphone.

>>> m = re.search(r"(\s*Tel\.:\s*(?P<telephone>.+?)\.)?", s) 
>>> m 
<_sre.SRE_Match object at 0x9369890> 
>>> m.group("telephone") 

Quel est le problème ici? Merci!

Edit:

Cela fait partie d'une plus grande expression régulière dans laquelle je reçois de nombreuses valeurs de chaque ligne d'un gros fichier.

regex = r"^(?P<title>.[^(]+);" \ 
     "\s*(?P<subtitle>.+)\." \ 
     "\s*Tel\.:\s*(?P<telephone>.+?)(\.|;)" \ 
     "\s*(?P<url>(www\.|http://).+?\.[a-zA-Z]+)(\.|;)" \ 
     "(\s*(?P<text>.+?)\.)?" \ 
     "\s*coor:(\s*(?P<lat>.+?),\s*(?P<long>.+?))?$" 

ligne Un exemple pourrait être:

l = "Title title; Subtitle, subtitle. Tel.: 555 33 44 11. www.url.com. coor: 11.11111, -2.222222 

Et autre ligne exemple:

l = "Title2 title; Subtitle2, subtitle. Tel.: 555 33 44 11. www.url2.com. coor: 44.444444, -6.66666 

Il est un regex vraiment grand, donc voilà pourquoi je ne l'ai pas poster.

Répondre

0

Votre regex est trop dans ce que les non spécifiques title et subtitle bits sont correspondent. Ils engloutissent la partie téléphonique, et si cela est facultatif, elle continue à la partie suivante de l'expression rationnelle (et réussit). Seulement si ce n'est pas optionnel, le moteur regex doit revenir en arrière pour trouver une correspondance globale.

Essayez

regex = r"^(?P<title>[^;]+);" \ 
     "\s*(?P<subtitle>[^.]+)\." \ 
     "(\s*Tel\.:\s*(?P<telephone>.+?)(\.|;))?" \ 
     "\s*(?P<url>(www\.|http://).+?\.[a-zA-Z]+)(\.|;)" \ 
     "(\s*(?P<text>.+?)\.)?" \ 
     "\s*coor:(\s*(?P<lat>.+?),\s*(?P<long>.+?))?$" 
+0

Vous où droit! Merci à vous et à tous pour votre aide :) – Menda

2

(anything)? correspond à la chaîne zéro au tout début de votre chaîne (avant Blah), elle est donc satisfaite et ne cherche pas plus loin.

EDIT:

Si vous avez plusieurs lignes et que certains d'entre eux contiennent la chaîne désirée, essayez ce qui suit:

import re 

rex = re.compile(r"\s*Tel\.:\s*(?P<telephone>.+?)\.") 
for line in lines: 
    m = rex.search(line) 
    if m: 
     print m.group("telephone") 
+1

s/esprit/peine/g –

+0

@ Tim, merci, exactement! – eumiro

2

En effet, une chaîne vide est un match valable pour l'expression régulière et est préféré sur la plus longue correspondance.

Vous voudrez peut-être jeter un coup d'œil à re.findall.

modifier: Vous pouvez déplacer l'optionalité de votre expression régulière tout à fait:

import re 
s = "Blah. Tel.: 555 44 33 22." 
m = re.search(r"\s*Tel\.:\s*(?P<telephone>.+?)\.", s) 
if m is not None: 
    print m.group("telephone") 
+0

Merci, et comment puis-je éviter ce comportement «paresseux»? – Menda

+0

Essayez 're.findall'. Cela vous donnera tous les matchs (vides ou non.) – NPE

+0

@Menda - pourquoi voulez-vous faire cela? Vous obtiendrez beaucoup de matchs vides. – eumiro

Questions connexes