2010-12-09 12 views
2

Die Zeichenfolge s ist größer, aber ich habe es verkürzt zu vereinfachen.Optionale Zeichenfolge nicht im regulären Ausdruck

>>> 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' 

Der obige Code funktioniert, aber wenn ich die Regex in ()? wickeln, um es optional zu machen, ich bekomme kein Telefon.

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

Was ist das Problem hier? Vielen Dank!

Edit:

Dieser Teil eines größeren regulären Ausdruck ist, in der ich viele Werte aus jeder Zeile einer großen Datei bin immer.

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>.+?))?$" 

Eine Probenleitung könnte sein:

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

und andere Probenleitung:

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

Es ist eine wirklich große regex, ist also, warum ich es nicht schreiben habe.

Antwort

0

Ihre regex ist zu unspezifisch, was die title und subtitle Bits passen: Sie haben die Optionalität aus Ihrem regulären Ausdruck überhaupt bewegen kann. Sie verschlingen den Telefonteil, und wenn dies optional gemacht wird, geht es beim nächsten Teil der Regex weiter (und ist erfolgreich). Nur wenn es nicht optional ist, muss die Regex-Engine zurückverfolgt werden, damit sie eine Gesamtübereinstimmung finden kann.

Versuchen

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

Sie waren richtig! Danke dir und allen für die Hilfe :) – Menda

2

(anything)? entspricht die Null-Zeichenfolge am Anfang der Zeichenfolge (vor Blah), so ist es glücklich und nicht weiter suchen.

EDIT:

Wenn Sie viele Zeilen haben und einige von ihnen nur die gewünschte Zeichenfolge enthalten, versuchen Sie Folgendes:

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/Geist/stören/g –

+0

@ Tim, danke, genau! – eumiro

2

Dies liegt daran, eine leere Zeichenfolge ein gültiges Spiel für Ihren regulären Ausdruck ist und wird gegenüber dem längeren Match bevorzugt.

Vielleicht möchten Sie einen Blick auf werfen.

bearbeiten:

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

Danke, und wie kann ich dieses "faule" Verhalten vermeiden? – Menda

+0

Versuchen Sie 're.findall'. Dadurch erhalten Sie alle Übereinstimmungen (leer oder nicht). – NPE

+0

@Menda - warum möchten Sie das tun? Du wirst viele leere Matches bekommen. – eumiro