re.findall()并不像预期的那样贪婪 - Python 2.7

Lee*_*rds 3 python regex findall

我试图使用python 2.7中的正则表达式从明文体中提取完整句子的列表.为了我的目的,将所有可以解释为完整句子的内容放在列表中并不重要,但列表中的所有内容都需要是一个完整的句子.以下是将说明问题的代码:

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

根据这个正则表达式测试器,理论上我应该得到这样的列表:

>>> ["Hello World!", "This is your captain speaking."]
Run Code Online (Sandbox Code Playgroud)

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

>>> [' World', ' speaking']
Run Code Online (Sandbox Code Playgroud)

文件指出的findall搜索从左至右和*和+运营商都贪婪地处理.感谢帮助.

Ray*_*ger 5

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

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

使用re.finditer()和探索匹配对象很容易看到发生了什么:

>>> 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',)
Run Code Online (Sandbox Code Playgroud)

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

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