Python regex.sub()为re.sub()提供了不同的结果

Python regex.sub()为re.sub()提供了不同的结果,python,regex,python-3.x,Python,Regex,Python 3.x,我在Python 3.4中使用重音文本 调用regex对重音句子执行替换效果很好,但使用用编译的regex然后调用失败 在这里,我对和使用相同的参数 重新导入 pattern=r'(?As,这实际上不是一个bug 然而,它与一个你没有遇到的bug有关,与你使用了一个你可能不应该使用的标志有关,所以我将在下面留下我先前的答案,即使他是你问题的正确答案 最近有一个ish更改(介于3.4.1和3.4.3之间,以及介于2.7.3和2.7.8之间)影响了这一点。在该更改之前,您甚至无法编译该模式而不引发

我在Python 3.4中使用重音文本

调用regex对重音句子执行替换效果很好,但使用用编译的regex然后调用失败

在这里,我对和使用相同的参数

重新导入
pattern=r'(?As,这实际上不是一个bug

然而,它与一个你没有遇到的bug有关,与你使用了一个你可能不应该使用的标志有关,所以我将在下面留下我先前的答案,即使他是你问题的正确答案


最近有一个ish更改(介于3.4.1和3.4.3之间,以及介于2.7.3和2.7.8之间)影响了这一点。在该更改之前,您甚至无法编译该模式而不引发
溢出错误

更重要的是,为什么要使用
re.L
re.L
机制并不意味着“对我的语言环境使用Unicode规则”,而是意味着“使用一些未指定的非Unicode规则,这些规则只对拉丁语派生的语言环境有意义,并且可能无法在Windows上正常工作”。或者,正如所说:

使
\w
\w
\b
\b
\s
\s
依赖于当前区域设置。不鼓励使用此标志,因为区域设置机制非常不可靠,并且它只处理一个“区域性”无论如何,每次都应该使用Unicode匹配,这是Python3中Unicode(str)模式的默认设置

有关这方面的一些最新讨论,请参阅和链接的python开发线程

如果我去掉
re.L
标志,代码现在在3.4.1上编译得很好。(我也得到了“正确的”3.4.1和3.4.3上的结果,但这只是巧合;我现在故意不在第一个版本中传递扭曲的标志并将其拧紧,但仍然意外地没有在第二个版本中传递扭曲的标志并将其拧紧,因此它们匹配……)


因此,即使这是一个bug,它也很有可能在WONTFIX中被关闭。#22407的解决方案是在3.5中反对
re.L
bytes
模式,并在3.6中删除它,所以我怀疑现在是否有人会在意用它修复bug。(更不用说,
re
本身在理论上正走向这几十年中的一个……而IIRC,
regex
也不赞成使用
L
标志,除非您使用的是
bytes
模式和
re
兼容模式。)

编译中的最后一个参数是
标志
,如果您在
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(模式、应答、字符串、计数=0、标志=0)


重新编译(模式,标志=0)

这很可能是一个bug-我可以在Windows 7上的空闲3.4.1上复制它,并期望这两种表单的输出相同。当我在自制的3.4.1上尝试这一点时,我发现
溢出错误:在
重新编译
行中,正则表达式代码大小超过了限制。与python.org中的3.3.2相同,并且(在添加了
u
前缀后)MacPorts的2.7.3。但是3.5alpha主干和3.4树的本地版本,以及Apple的2.7.6,都可以正常工作。这意味着在这个模式中有一个相当新的错误修复,这使得看起来更可能仍然有一个错误潜伏在那里…(我建议搜索最近的错误修复程序,以便您可以在新的错误中链接到它。)更改
.sub()
调用的顺序会改变什么吗?@user3012759问得好!但不会。等等……为什么您首先要使用
re.L
?对于Unicode模式,它的作用并没有超出定义范围“您不应该使用它”,但它是(在CPython中)实现的就像一些你几乎永远不会想要的时髦的拉丁语-1特定规则,尤其是东欧文本中的规则。通过快速测试,如果删除该标志,它将修复3.4.1中的异常,并修复3.4.3中不正确的结果。太棒了!但是描述有点混乱。他已经知道
compile
中的大参数是
flags
;问题是
sub
的第四个参数不是
flags
,而是
count
。因此,他实际上传递的是
count=6,flags=0
(这就是为什么当有多个关键字参数时,您应该始终使用关键字参数的原因。)@abarnert,是的,他忘了添加那部分。干杯。有趣的是,他实际上有两个bug相互抵消。这是第一个,他不小心将
标志
传递为
计数
,返回他想要的结果,因为这防止了
re.L
标志破坏东西……哎哟,我怎么没发现呢!啊然而,正是出于这个原因,这样对参数进行排序似乎有点愚蠢。@jornsharpe:IIRC,
flags
在原始的
(s)re
模块中不存在。当它在2.3左右版本中添加时,唯一合理的做法是在所有现有参数之后将其添加到每个函数中。(好吧,真正合理的做法是将其设置为仅限关键字的参数,但当时没有人这么想。)感谢您的帮助。
re.sub()
中的参数顺序错误导致了
re.sub()
regex.sub()之间的结果不同
和有争议的
re.L
标志导致模式不匹配。这个糟糕的巧合让我困惑,你的解释治好了我的头痛。
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)