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

时间:2015-04-13 09:38:38

标签: python regex python-3.x

我使用Python 3.4中的Czech重音文本。

调用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

我认为原因是重音,因为非重音句re.sub()regex.sub()的作用相同。

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

Python console

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

2 个答案:

答案 0 :(得分:14)

作为Padraic Cunningham figured out,这实际上并不是一个错误。

然而,相关是一个你没有遇到过的错误,并且你使用的标志你可能不应该使用,所以我会这样做留下我之前的答案,即使他是你问题的正确答案。


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

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

  

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

请参阅bug #22407和链接的python-dev线程,以了解最近对此的一些讨论。

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

所以,即使这是一个错误,也很有可能会关闭WONTFIX。 #22407的解决方案是弃用re.L替换3.5中的非bytes模式并将其删除3.6,所以我怀疑任何人现在都不关心修复错误。 (更不用说re本身在理论上有利于regex这些年中的一个......而且IIRC,regex也弃用了L旗帜,除非你&#39;重新使用bytes模式和re - 兼容模式。)

答案 1 :(得分: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)

re.sub的第四个结果是count,这就是您看到差异的原因。

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

re.compile(pattern,flags = 0)