arm*_*ino 15 python regex search string-matching findall
我需要在给定正则表达式的字符串中找到所有匹配项.我一直在findall()
这样做,直到我遇到一个没有按照我的预期做的情况.例如:
regex = re.compile('(\d+,?)+')
s = 'There are 9,000,000 bicycles in Beijing.'
print re.search(regex, s).group(0)
> 9,000,000
print re.findall(regex, s)
> ['000']
Run Code Online (Sandbox Code Playgroud)
在这种情况下search()
返回我需要的(最长匹配)但findall()
行为不同,虽然文档暗示它应该是相同的:
findall()
匹配所有出现的模式,而不仅仅是第一个模式search()
.
为什么行为不同?
我怎样才能实现的结果search()
与findall()
(或别的东西)?
ale*_*ull 18
好的,我从文档中看到了...
如果模式中存在一个或多个组,则返回组列表; 如果模式有多个组,这将是一个元组列表.
事实证明,你有一个组,"(\ d +,?)"......所以,它返回的是该组的最后一次出现,或000.
一种解决方案是围绕整个正则表达式,像这样
regex = re.compile('((\d+,?)+)')
Run Code Online (Sandbox Code Playgroud)
然后,它将返回[('9,000,000','000')],这是一个包含两个匹配组的元组.当然,你只关心第一个.
就个人而言,我会使用以下正则表达式
regex = re.compile('((\d+,)*\d+)')
Run Code Online (Sandbox Code Playgroud)
避免匹配"这是一个坏号码9,123"之类的东西
编辑.
这是一种避免用括号括起表达式或处理元组的方法
s = "..."
regex = re.compile('(\d+,?)+')
it = re.finditer(regex, s)
for match in it:
print match.group(0)
Run Code Online (Sandbox Code Playgroud)
finditer返回一个迭代器,您可以使用它来访问找到的所有匹配项.这些匹配对象与re.search返回的相同,因此group(0)返回您期望的结果.
@ aleph_null的答案正确解释了导致问题的原因,但我认为我有更好的解决方案.使用这个正则表达式:
regex = re.compile(r'\d+(?:,\d+)*')
Run Code Online (Sandbox Code Playgroud)
为什么它更好的一些原因:
(?:...)
是一个非捕获组,因此您只能获得每个匹配的一个结果.
\d+(?:,\d+)*
是一个更好的正则表达式,更高效,更不容易返回误报.
如果可能的话,你应该总是使用Python的原始字符串作为正则表达式; 你就不太可能通过正则表达式转义序列(如惊讶\b
的字边界)被解释为字符串字面转义序列(如\b
为退格键).