在Python 3.7上,re.sub(“.*",“,“(替换)",“text”)对替换进行双精度运算

4ktjp1zp  于 2022-11-27  发布在  Python
关注(0)|答案(2)|浏览(129)

在Python 3.7上(在Windows 64位上测试),使用RegEx .*替换字符串会使输入字符串重复两次!
在Python 3.7.2上:

>>> import re
>>> re.sub(".*", "(replacement)", "sample text")
'(replacement)(replacement)'

在Python 3.6.4上:

>>> import re
>>> re.sub(".*", "(replacement)", "sample text")
'(replacement)'

在Python 2.7.5(32位)上:

>>> import re
>>> re.sub(".*", "(replacement)", "sample text")
'(replacement)'

怎么了?怎么解决?

1zmg4dgp

1zmg4dgp1#

这不是一个bug,而是Python 3.7中来自提交fbb490fd2f38bd817d99c20c05121ad0168a38ee的bug修复。
在正则表达式中,非零宽度的匹配将指针位置移动到匹配的末尾,以便下一个Assert(无论是否为零宽度)可以从匹配后的位置继续匹配。指针随后移动到字符串末尾的事实实际上仍然为该位置的零宽度匹配留下了“空间,”这一点从下面的代码中可以明显看出,它在Python 2.7、Python 3.6和Python 3.7中的行为相同:

>>> re.findall(".*", 'sample text')
['sample text', '']

因此,这个错误修复程序(关于在非零宽度匹配之后替换零宽度匹配)现在可以正确地用替换文本替换这两个匹配。

pgky5nke

pgky5nke2#

这是一个常见的正则表达式问题,它影响了许多正则表达式风格,请参见相关

有几种方法可以解决此问题:

  • .*的两侧加入锚点:re.sub("^.*$", "(replacement)", "sample text")
  • 由于您只想匹配一行一次,因此添加count=1参数:print( re.sub(".*", "(replacement)", "sample text", count=1) )
  • 如果要替换任何非空行,请将*替换为+print( re.sub(".+", "(replacement)", "sample text") )

请参阅Python demo

import re
# Adding anchors:
print( re.sub("^.*$", "(replacement)", "sample text") ) # => (replacement)
# Using the count=1 argument
print( re.sub(".*", "(replacement)", "sample text", count=1) ) # => (replacement)
# If you want to replace non-empty lines:
print( re.sub(".+", "(replacement)", "sample text") ) # => (replacement)

相关问题