Python 正则表达式非贪婪表现得像贪婪

Python regex non-greedy acting like greedy

我正在处理成绩单,但在以非贪婪方式匹配模式时遇到了问题。它仍然抢得太多,看起来像是在进行贪婪的比赛。

成绩单如下所示:

>> John Doe:大家好,我是John Doe。

>> 大家好,我是李四。

>> 感谢您的光临,我们将在两分钟后开始。

>> Sam Smith:[无音频]大家早上好。

要在 >>(任意姓名): 中查找演讲者姓名,我写了

pattern=re.compile(r'>>(.*?):')
transcript='>> John doe: Hello, I am John Doe. >> Hello, I am Jane Doe. >> Thank you for coming, we will start in two minutes. >> Sam Smith: [no audio] Good morning, everyone.'
re.findall(pattern, transcript)

我期望 'John Doe''Sam Smith',但它给了我 'John Doe''Hello, I am Jane Doe. >> Thank you for coming, we will start in two minutes. >> Sam Smith'

我很困惑,因为.*?是非贪婪的,(我认为)应该可以抢到'Sam Smith'。我应该如何修复代码,以便它只抓取任何内容 >>(随便什么名字):?另外,我正在使用 Python 3.6.

谢谢!

你真的需要正则表达式吗?您可以拆分 >> 个提示,然后过滤掉您的名字。

>>> [i.split(':')[0].strip() for i in transcript.split('>>') if ':' in i]
['John doe', 'Sam Smith']

您对非贪婪正则表达式的理解略有偏差。非贪婪意味着它将匹配从开始匹配开始可能的最短匹配。如果在匹配中找到另一个字符,它不会更改开始匹配的字符。

例如:

start.*?stop

将匹配所有 startstartstop,因为一旦它在 start 处开始匹配,它将一直匹配直到找到停止。非贪婪只是意味着对于字符串 startstartstopstop,它只会匹配到第一站。

对于你的问题,这是一个使用正向前瞻很容易解决的问题。

您可以使用 >> ([a-zA-Z ]+)(?=:):

>>> transcript='>> John doe: Hello, I am John Doe. >> Hello, I am Jane Doe. >> Thank you for coming, we will start in two minutes. >> Sam Smith: [no audio] Good morning, everyone.'    
>>> re.findall(r'>> ([a-zA-Z ]+)(?=:)', transcript)
['John doe', 'Sam Smith']