正则表达式未匹配可选字符串
这个字符串 s
比较长,但我把它缩短了,方便理解。
>>> 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'
上面的代码是可以工作的,但如果我把正则表达式用 ()?
包起来,让它变成可选的,我就找不到任何电话号码了。
>>> m = re.search(r"(\s*Tel\.:\s*(?P<telephone>.+?)\.)?", s)
>>> m
<_sre.SRE_Match object at 0x9369890>
>>> m.group("telephone")
这里面有什么问题呢?谢谢!
补充:
这是一个更大正则表达式的一部分,我正在从一个大文件的每一行中提取很多值。
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>.+?))?$"
一行示例可能是:
l = "Title title; Subtitle, subtitle. Tel.: 555 33 44 11. www.url.com. coor: 11.11111, -2.222222
还有另一行示例:
l = "Title2 title; Subtitle2, subtitle. Tel.: 555 33 44 11. www.url2.com. coor: 44.444444, -6.66666
这个正则表达式真的很复杂,所以我没有把它贴出来。
3 个回答
2
(anything)?
这个表达式会在你的字符串最开始的位置(在 Blah
之前)匹配到一个空字符串,所以它就满足了条件,不会继续往下查找了。
编辑:
如果你有很多行文本,而只有其中一些行包含你想要的字符串,可以试试下面的方法:
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")
2
这是因为空字符串是你的正则表达式可以匹配的有效结果,而且它比更长的匹配结果更受欢迎。
你可能想看看 re.findall
。
编辑: 你可以把可选的部分完全移出你的正则表达式:
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
你的正则表达式对 title
和 subtitle
的匹配规则太宽泛了。它们把电话号码的部分也包含进去了,如果把电话号码设为可选的,正则表达式就会继续匹配后面的部分(并且成功匹配)。只有在电话号码不是可选的情况下,正则引擎才会回溯,才能找到一个整体的匹配。
可以试试
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>.+?))?$"