为何Python re模块中search与findall对同一正则匹配结果不一致?
Python re模块search与findall匹配结果不一致的原因
问题现象
使用同一正则表达式匹配IP地址时,search()能正确返回完整IP的匹配对象,但findall()返回的却是正则分组的内容,而非完整IP:
代码示例:
import re msg = 'data from 192.168.10.255 and 10.10.10.10' ipregex_d = re.compile('((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])') op = ipregex_d.search(msg) print(op) op = ipregex_d.findall(msg) print(op)
输出结果:
<re.Match object; span=(10, 24), match='192.168.10.255'> # search返回完整IP的匹配对象 [('10.', '10', '255'), ('10.', '10', '10')] # findall返回分组内容,而非完整IP
核心原因
两者的行为差异完全由正则表达式中的捕获分组导致:
search()返回单个匹配对象,默认打印时展示的是整个匹配内容(即group(0)),如需查看分组内容可调用match.groups();findall()的规则是:如果正则包含捕获分组,它会返回所有分组匹配结果组成的元组列表;只有当正则没有任何捕获分组时,才会返回整个匹配的字符串列表。
你的正则里嵌套了多层捕获分组:最外层的((...)\.){3}是一个捕获分组,内部的(25[0-5]...)也是捕获分组,最后还有一个单独的捕获分组,所以findall()会返回这些分组的内容,而非完整IP。
解决方案
方案1:改用非捕获分组(推荐)
把正则中不需要单独捕获的分组改成非捕获分组(?:...),这样findall()就会返回整个匹配的完整IP:
修改后的代码:
import re msg = 'data from 192.168.10.255 and 10.10.10.10' # 所有分组都改为非捕获分组(?:...) ipregex_d = re.compile('(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])') op = ipregex_d.search(msg) print(op) op = ipregex_d.findall(msg) print(op)
输出结果:
<re.Match object; span=(10, 24), match='192.168.10.255'> ['192.168.10.255', '10.10.10.10']
方案2:用finditer获取匹配对象(保留分组需求时用)
如果需要同时获取完整IP和分组内容,可以用finditer()返回匹配对象迭代器,逐个提取所需内容:
import re msg = 'data from 192.168.10.255 and 10.10.10.10' ipregex_d = re.compile('((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])') for match in ipregex_d.finditer(msg): print(f"完整IP: {match.group(0)}") print(f"分组内容: {match.groups()}\n")
输出结果:
完整IP: 192.168.10.255 分组内容: ('10.', '10', '255') 完整IP: 10.10.10.10 分组内容: ('10.', '10', '10')
内容的提问来源于stack exchange,提问作者Majoris
相关产品推荐
相关产品推荐

