python - 正则表达式搜索和 findall
Posted
技术标签:
【中文标题】python - 正则表达式搜索和 findall【英文标题】:python - regex search and findall 【发布时间】:2011-12-27 22:41:49 【问题描述】:我需要在字符串中为给定的正则表达式找到所有匹配项。我一直在使用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']
在这种情况下,search()
返回我需要的内容(最长匹配),但 findall()
的行为不同,尽管文档暗示它应该是相同的:
findall()
匹配所有出现的模式,而不仅仅是第一个 正如search()
所做的那样。
为什么行为不同?
如何使用findall()
(或其他)实现search()
的结果?
【问题讨论】:
【参考方案1】:好的,我知道发生了什么……来自文档:
如果模式中存在一个或多个组,则返回组列表; 如果模式有多个组,这将是一个元组列表。
事实证明,您确实有一个组“(\d+,?)”...所以,它返回的是该组的最后一次出现,即 000。
一种解决方案是用一个组包围整个正则表达式,像这样
regex = re.compile('((\d+,?)+)')
然后,它将返回 [('9,000,000', '000')],这是一个包含两个匹配组的元组。当然,你只关心第一个。
就个人而言,我会使用以下正则表达式
regex = re.compile('((\d+,)*\d+)')
为了避免匹配诸如“这是一个错误的数字 9,123”之类的内容,
编辑。
这是一种避免用括号括住表达式或处理元组的方法
s = "..."
regex = re.compile('(\d+,?)+')
it = re.finditer(regex, s)
for match in it:
print match.group(0)
finditer 返回一个迭代器,您可以使用它来访问找到的所有匹配项。这些匹配对象与 re.search 返回的相同,因此 group(0) 返回您期望的结果。
【讨论】:
感谢您的解释。事实证明finditer
实际上更适合我按照您的建议所做的事情。正则表达式来自用户输入,因此我无法控制它。【参考方案2】:
@aleph_null 的answer 正确解释了导致您的问题的原因,但我认为我有更好的解决方案。使用这个正则表达式:
regex = re.compile(r'\d+(?:,\d+)*')
它更好的一些原因:
(?:...)
是一个非捕获组,因此每场比赛您只能得到一个结果。
\d+(?:,\d+)*
是一种更好的正则表达式,效率更高且返回误报的可能性更低。
如果可能,您应该始终将 Python 的原始字符串用于正则表达式;您不太可能对正则表达式转义序列(如 word 边界 的 \b
)被解释为字符串文字转义序列(如 退格 的 \b
)。
【讨论】:
谢谢艾伦!我之前应该提到过,但我无法控制正则表达式,因为它是用户输入.. 没问题!但是,为了记录,让用户输入要由您的应用程序执行的正则表达式是一个坏主意。当他们写得不好(或只是匆忙输入)的正则表达式无法匹配或导致系统崩溃时,他们会为此责备你。 ;)以上是关于python - 正则表达式搜索和 findall的主要内容,如果未能解决你的问题,请参考以下文章
正则表达式 findall start() 和 end() ? Python
python正则表达式01--贪心算法和非贪心算法findall()
python正则表达式re.findall(r"\b\w+\b", s)中的r是啥意思?