Python正则non-greedy模式表现如greedy模式的转录文本匹配问题
解决正则非贪婪模式看似过度匹配的问题
嘿,我来帮你搞定这个正则非贪婪模式失效的问题!你遇到的情况其实不是非贪婪模式真的没用,而是你的正则没有限制匹配范围,导致它会跨越多段>>内容去寻找下一个:,看起来就像贪婪模式一样。
问题根源分析
你的原正则r'>>(.*?):'里,(.*?)会匹配任意字符——包括后续的>>片段。而你的转录文本中,有些>>后面并没有跟着:(比如>> Hello, I am Jane Doe.),正则就会一直往后“搜刮”内容,直到找到下一个带:的>>条目(也就是Sam Smith:),自然就出现了过度匹配。
解决方案
这里给你两个实用的修正方案:
方案1:用字符集限定匹配范围(简单直接)
修改正则,让捕获组只匹配**不包含&**的内容(因为>>以&开头,这样就能避免跨段匹配),同时加上\s*匹配>>后的可选空格,确保提取的姓名不带前导空格:
import re 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.' pattern = re.compile(r'>>\s*([^&]+?):') matches = pattern.findall(transcript) print(matches) # 输出: ['John doe', 'Sam Smith']
[^&]+?是核心:[^&]表示匹配除&以外的任意字符,+?保持非贪婪特性,找到最近的:就停止,完美避开中间的>>片段。
方案2:用负向预查更精确(适合复杂场景)
如果你的姓名里可能包含&(虽然概率极低),可以用负向预查(?!>>)来确保匹配的内容中不出现完整的>>,这样逻辑更严谨:
import re 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.' pattern = re.compile(r'>>\s*((?:(?!>>).)*?):') matches = pattern.findall(transcript) print(matches) # 同样输出: ['John doe', 'Sam Smith']
(?:(?!>>).)*?的意思是:每次匹配一个字符前,先检查后面不是>>,直到遇到:为止,完全不会跨段匹配。
额外优化:清理姓名前后空格
如果担心提取的姓名前后有多余空格,可以直接用Python的strip()处理,或者在正则里优化:
# 方式1:匹配后清理 matches = [name.strip() for name in pattern.findall(transcript)] # 方式2:正则直接匹配非首尾空格的姓名 pattern = re.compile(r'>>\s*(\S(?:.*?\S)?):')
内容的提问来源于stack exchange,提问作者ybcha204
相关产品推荐
相关产品推荐

