使用re.findall()仅返回单个结果,如何获取预期多匹配结果?
正则提取边界词间文本的匹配问题
我尝试用re.findall()提取两个边界词之间的文本(包含边界词本身),示例代码如下:
description = 'White cat sat on the mat and then the cat ran away' starting_word = 'cat' ending_word = 'ran' detail_re = r'{0}.*?{1}'.format(starting_word, ending_word) extracted_text_list = re.findall(detail_re, description,re.IGNORECASE)
预期结果:
['cat sat on the mat and then the cat ran', 'cat ran']
实际结果:
['cat sat on the mat and then the cat ran']
解决方法
问题根源
当前正则采用左到右的非贪婪匹配,但匹配第一个结果时会消耗从第一个cat到ran的所有字符,导致第二个cat ran所在的子串已被覆盖,正则默认不会对已消耗的字符重复匹配。
修正方案
使用正向零宽断言实现重叠匹配,修改正则表达式如下:
import re description = 'White cat sat on the mat and then the cat ran away' starting_word = 'cat' ending_word = 'ran' # 用正向预查包裹捕获组,避免消耗字符,支持重叠匹配 detail_re = r'(?=({0}.*?{1}))'.format(re.escape(starting_word), re.escape(ending_word)) # 通过finditer遍历所有匹配,提取捕获组内容 extracted_text_list = [match.group(1) for match in re.finditer(detail_re, description, re.IGNORECASE)] print(extracted_text_list)
运行后即可得到预期结果:
['cat sat on the mat and then the cat ran', 'cat ran']
额外说明
- 加入
re.escape()处理起始/结束词,避免词中包含正则特殊字符(如.、*)时出现匹配异常。 - 正向零宽断言
(?=...)仅做匹配检查,不会消耗字符串中的字符,因此正则引擎可以逐个位置扫描,捕获所有符合条件的子串,包括重叠场景。
内容的提问来源于stack exchange,提问作者nr spider
相关产品推荐
相关产品推荐

