python re.sub的行为在3.7中发生了更改。虫子还是虫子?
我的一个python脚本在最近的版本中开始出现错误。我追踪到了一个在python=3.7中表现不同的python re.sub的行为在3.7中发生了更改。虫子还是虫子?,python,regex,python-3.x,Python,Regex,Python 3.x,我的一个python脚本在最近的版本中开始出现错误。我追踪到了一个在python=3.7中表现不同的re替换,较新的python版本将替换两次 pythonre中有什么东西坏了吗?还是我做错了什么,最后被抓住了 据我所知,下面示例代码中的regexr'[^\u]*$”应该匹配最后一个下划线之后的所有内容。。。如果没有下划线,则为整个字符串 在下面的示例中,Python3.6创建s==“a_Z”,而Python3.7创建“a_ZZ” $ docker run --rm python:3.6-al
re
替换,较新的python版本将替换两次
pythonre
中有什么东西坏了吗?还是我做错了什么,最后被抓住了
据我所知,下面示例代码中的regexr'[^\u]*$”
应该匹配最后一个下划线之后的所有内容。。。如果没有下划线,则为整个字符串
在下面的示例中,Python3.6创建s==“a_Z”,而Python3.7创建“a_ZZ”
$ docker run --rm python:3.6-alpine python -c "import re;s=re.sub(r'[^_]*$','Z','a_b');assert s == 'a_Z',s"
$ docker run --rm python:3.7-alpine python -c "import re;s=re.sub(r'[^_]*$','Z','a_b');assert s == 'a_Z',s"
Traceback (most recent call last):
File "<string>", line 1, in <module>
AssertionError: a_ZZ
$docker-run--rm-python:3.6-alpine-python-c“导入re;s=re.sub(r'[^.]*$,'Z','a_b');断言s=='a_Z',s”
$docker run--rm python:3.7-alpine python-c“导入re;s=re.sub(r'[^.]*$','Z','a_b');断言s=='a_Z',s”
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
断言错误:a_ZZ
与3.8-alpine、3.9-rc-buster的错误相同。根据:
在版本3.7中更改:当与以前的非空匹配相邻时,将替换模式的空匹配
在'a_b'
中有两个匹配的模式,因为模式包括*
:b
;然后是一根空火柴。您可以在中看到这一点,例如,或使用re.findall
:
>>> re.findall(r'[^_]*$', 'a_b')
['b', '']
如果切换到+
,您将获得预期结果。根据:
在版本3.7中更改:当与以前的非空匹配相邻时,将替换模式的空匹配
在'a_b'
中有两个匹配的模式,因为模式包括*
:b
;然后是一根空火柴。您可以在中看到这一点,例如,或使用re.findall
:
>>> re.findall(r'[^_]*$', 'a_b')
['b', '']
如果您切换到
+
,您将得到预期的结果。中有几个“在版本3.7中进行了更改”,您查看了吗?中有几个“在版本3.7中进行了更改”,您查看了吗?@MarkBorgerding有意义,任何删除或忽略空匹配项的操作。因此,看起来re.sub现在很容易出错,因为模式可以匹配空字符串。将count=1
添加到re.sub会限制替换,但是如果您不想替换空匹配项,是否有办法知道其中一个subst将最长(即不是空字符串),编写不提供空匹配的模式(正如我在回答中所建议的,r'[^\u]+$'
可以工作)。我不会将其描述为容易出错,这一更改是一个错误修复。其基本原理是@MarkBorgerding,任何删除或忽略空匹配的内容都是有意义的。因此,看起来re.sub现在非常容易出错,模式可以匹配空字符串。添加count=1
到re.sub会限制替换,但是,如果您不想替换空匹配项,那么有没有办法知道一个subst将是最长的(即不是空字符串),请编写不提供空匹配项的模式(正如我在回答中所建议的,r'[^\u]+$”
)。我不会把它描述为容易出错的,这种更改是一个错误修复