【问题标题】:re.findall() isn't as greedy as expected - Python 2.7re.findall() 并不像预期的那么贪婪 - Python 2.7
【发布时间】:2017-10-05 03:38:23
【问题描述】:

我正在尝试使用 python 2.7 中的正则表达式从纯文本正文中提取完整句子的列表。就我的目的而言,可以解释为完整句子的所有内容都应该在列表中并不重要,但列表中的所有内容都必须是完整的句子。下面是说明问题的代码:

import re
text = "Hello World! This is your captain speaking."
sentences = re.findall("[A-Z]\w+(\s+\w+[,;:-]?)*[.!?]", text)
print sentences

根据regex tester,理论上我应该得到这样的列表:

>>> ["Hello World!", "This is your captain speaking."]

但我实际得到的输出是这样的:

>>> [' World', ' speaking']

documentation 表示 findall 从左到右搜索,并且 * 和 + 运算符被贪婪地处理。感谢您的帮助。

【问题讨论】:

  • 当您将捕获组与 re.findall 一起使用时,它只返回捕获集而不是整个匹配。将您的捕获组(...) 更改为非捕获组(?:...)(以及第一个\w+\w*。你的问题与贪婪无关。
  • 是的,这行得通。谢谢你。
  • 这不是 stackoverflow.com/questions/31915018/… 的完全相同的副本。在那个问题中,在原始字符串中存在双重转义\\ 的混淆问题。这个问题更清楚地触及了一个问题的核心,即给定捕获组时 re.findall() 的行为。

标签: python regex findall


【解决方案1】:

问题在于 findall() 只显示捕获的子组而不是完整匹配。根据re.findall() 的文档:

如果模式中存在一个或多个组,则返回一个列表 团体;如果模式有多个,这将是一个元组列表 组。

使用re.finditer() 并探索match objects 很容易看到发生了什么:

>>> import re
>>> text = "Hello World! This is your captain speaking."

>>> it = re.finditer("[A-Z]\w+(\s+\w+[,;:-]?)*[.!?]", text)

>>> mo = next(it)
>>> mo.group(0)
'Hello World!'
>>> mo.groups()
(' World',)

>>> mo = next(it)
>>> mo.group(0)
'This is your captain speaking.'
>>> mo.groups()
(' speaking',)

解决您的问题的方法是使用?: 抑制子组。然后你会得到预期的结果:

>>> re.findall("[A-Z]\w+(?:\s+\w+[,;:-]?)*[.!?]", text)
['Hello World!', 'This is your captain speaking.'

【讨论】:

    【解决方案2】:

    你可以稍微改变你的正则表达式:

    >>> re.findall(r"[A-Z][\w\s]+[!.,;:]", text)
    ['Hello World!', 'This is your captain speaking.']
    

    【讨论】:

      猜你喜欢
      • 2021-10-07
      • 2017-07-13
      • 1970-01-01
      • 2011-11-09
      • 2020-09-28
      • 2017-08-07
      • 1970-01-01
      • 2012-06-06
      • 1970-01-01
      相关资源
      最近更新 更多