Python 3.6与3.10中re.sub方法的差异疑问
Python 3.6与3.10正则
re.sub行为差异原因及解决办法 这个差异是Python 3.7及以上版本对re.sub处理零长度匹配的逻辑调整导致的,属于模块的正常行为变更,并非退化问题。
具体原因分析
你用的正则表达式r'[0-9]*$'里,*表示匹配0次或多次数字,所以它既会匹配末尾的数字(比如示例中的'4'),也会匹配字符串末尾的空字符串(0次数字也符合规则)。
- 在Python 3.6及更早版本中,
re.sub完成一次非零长度匹配的替换后,不会继续匹配后续的零长度结果,所以只把'4'替换成'0',得到'1.2.3.0'。 - 在Python 3.7+(包括3.10.6)中,
re.sub的匹配逻辑更新:替换完非零长度的匹配后,会继续检查当前位置的零长度匹配。这里替换'4'为'0'后,引擎停在字符串末尾,此时末尾的空字符串符合[0-9]*$的规则,于是又把空字符串替换成'0',最终得到'1.2.3.00'。
解决办法
根据你的预期结果,有两种常用修复方式:
- 修改正则表达式:把
*改成+,即r'[0-9]+$',+表示匹配至少一次数字,不会匹配末尾的空字符串,两个版本都会得到预期结果。
代码示例:import re RE_IP = re.compile(r'[0-9]+$') print(RE_IP.sub('0', '1.2.3.4')) # 输出: '1.2.3.0' - 限制替换次数:在
sub方法中加count=1参数,强制只替换一次匹配结果,无视后续符合规则的匹配:
代码示例:import re RE_IP = re.compile(r'[0-9]*$') print(RE_IP.sub('0', '1.2.3.4', count=1)) # 输出: '1.2.3.0'
内容的提问来源于stack exchange,提问作者Pavel Francírek
相关产品推荐
相关产品推荐

