regex.sub()给re.sub()提供不同的结果

Vac*_*tny 14 python regex python-3.x

我在Python 3.4中使用捷克语重音文本.

调用re.sub()正则表达式对重音句子执行替换效果很好,但是使用正则表达式编译re.compile()然后调用regex.sub()失败.

在这种情况下,我使用相同的参数re.sub()regex.sub()

import re

pattern = r'(?<!\*)(Poplatn[ií]\w+ da[n?]\w+)'
flags = re.I|re.L
compiled = re.compile(pattern, flags)
text = 'Poplatníkem dan? z pozemk? je vlastník pozemku'
mark = r'**\1**' # wrap 1st matching group in double stars

print(re.sub(pattern, mark, text, flags))
# outputs: **Poplatníkem dan?** z pozemk? je vlastník pozemku
# substitution works

print(compiled.sub(mark, text))
# outputs: Poplatníkem dan? z pozemk? je vlastník pozemku
# substitution fails
Run Code Online (Sandbox Code Playgroud)

我认为原因是口音,因为对于非重音句re.sub()regex.sub()工作相同.

但在我看来,它似乎是一个错误,因为传递相同的参数会返回不同的结果,这不应该发生.此主题因不同的平台和区域设置而变得复杂,因此在您的系统上可能无法重现.这是我的控制台的屏幕截图.

Python控制台

您是否在我的代码中看到任何错误,或者我应该将其报告为错误?

aba*_*ert 14

正如Padraic Cunningham所知,这实际上并不是一个错误.

但是,它你没有碰到的一个错误有关,并且你使用的标志你可能不应该使用,所以我将在下面留下我的早期答案,即使他是你问题的正确答案.


最近的变化(介于3.4.1和3.4.3之间,介于2.7.3和2.7.8之间)会影响这一点.在更改之前,您甚至无法编译该模式而不提高OverflowError.

更重要的是,你为什么用re.L?该re.L机制并不意味着"对我的语言环境使用Unicode规则",它意味着"使用一些未指定的非Unicode规则,这些规则只对Latin-1派生的语言环境有意义,并且可能无法在Windows上正常工作".或者,正如文档所说:

\w,\W,\b,\B,\s以及\S依赖于当前的语言环境.不鼓励使用此标志,因为语言环境机制非常不可靠,并且它一次只能处理一个"文化"; 你应该使用Unicode匹配,这是Python 3中针对Unicode(str)模式的默认设置.

有关此问题的最新讨论,请参阅错误#22407和链接的python-dev线程.

如果我删除该re.L标志,代码现在编译就好了3.4.1.(我也得到了3.4.1和3.4.3的"正确"结果,但这只是一个巧合;我现在故意不通过螺旋旗并在第一个版本中拧紧它,但仍然意外地没有通过在第二个拧紧旗帜,所以他们匹配...)

所以,即使这是一个bug,也很有可能它将被关闭WONTFIX.#22407的解决方案是弃用3.5中的re.Lbytes模式并在3.6中删除它,所以我怀疑任何人都会关心用它来修复bug.(更不用说它re本身在理论上有利于regex这几十年中的一个......而且IIRC regex也弃用了L旗帜,除非你使用bytes模式和re兼容模式.)


Pad*_*ham 10

编译中的最后一个参数是flags,如果您实际使用flags=flags,re.sub您将看到相同的行为:

compiled = re.compile(pattern, flags)
print(compiled)
text = 'Poplatníkem dan? z pozemk? je vlastník pozemku'
mark = r'**\1**' # wrap 1st matching group in double stars

r = re.sub(pattern, mark, text, flags=flags)
Run Code Online (Sandbox Code Playgroud)

第四个结果re.subcount这就是为什么你看到差异.

re.sub(pattern,repl,string,count = 0,flags = 0)

re.compile(pattern,flags = 0)

  • 哎呀,我怎么没有发现那个!但是,对这些参数进行排序似乎有点愚蠢,正是出于这个原因. (2认同)