Python re模块search与findall方法匹配结果不一致的原因
问题原因
两个方法返回结果不一致,本质是Python标准库re模块中search()和findall()的返回规则存在核心差异,和模式是否匹配成功没有直接关系:
re.search()的逻辑是扫描整个字符串,只要找到第一个符合整个正则模式的匹配片段,就返回对应的Match对象,完全不关心正则内部有没有分组、分组捕获到什么内容。示例中的模式Bat(wo)?man里(wo)?代表匹配0次或1次wo,字符串里的Batman完全符合整个模式的匹配规则,所以search能正常返回匹配结果。re.findall()的返回规则受正则中的捕获组影响非常大:- 正则中没有捕获组时,返回所有匹配整个模式的字符串组成的列表
- 正则中有1个捕获组时,不会返回整个匹配的内容,而是返回每个匹配位置上,该捕获组匹配到的内容组成的列表
- 正则中有多个捕获组时,返回由元组组成的列表,每个元组按顺序对应各个分组的匹配内容
你观察到的"findall返回空列表"是视觉误判:带捕获组的模式匹配Batman时,(wo)?匹配了0次,这个捕获组没有捕获到实际字符,所以findall返回的是['']——列表里只有一个空字符串,打印时没有可见内容,很容易被当成空列表。
修复方法
如果需要让findall返回整个模式的匹配结果,把不需要单独提取内容的分组改成非捕获组即可,非捕获组的写法是(?:匹配规则),不会被findall当做返回内容的依据。
修正后的可运行代码如下:
import re # search匹配整个片段,正常返回结果 search_result = re.search(r'Bat(wo)?man', 'The Adventures of Batman') print(search_result.group()) # 输出:Batman # 带普通捕获组的findall,返回分组捕获的空字符串 findall_with_capture = re.findall(r'Bat(wo)?man', 'The Adventures of Batman') print(findall_with_capture) # 输出:[''] # 改用非捕获组后,findall返回整个匹配片段 findall_fixed = re.findall(r'Bat(?:wo)?man', 'The Adventures of Batman') print(findall_fixed) # 输出:['Batman']
内容的提问来源于stack exchange,提问作者Karl King
相关产品推荐
相关产品推荐

