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是啥意思?

python正则表达式02--findall()和search()方法区别,group()方法

python 正则表达式

Python面试必考重点之字符串与正则表达式第十二关——findall函数的使用