python - 不可能的反向引用

标签 python regex python-3.x python-2.7

据我了解,

(.)(?<!\1)

不应该匹配。实际上,php 的 preg_replace 甚至拒绝编译它,ruby 的 gsub 也是如此。 python re 模块似乎有不同的意见:

import re
test = 'xAAAAAyBBBBz'
print (re.sub(r'(.)(?<!\1)', r'(\g<0>)', test))

结果:

(x)AAAA(A)(y)BBB(B)(z)

谁能为这种行为提供合理的解释?

更新

此行为似乎是 a limitationre 模块中。替代品regex模块似乎正确处理断言中的组:

import regex

test = 'xAAAAAyBBBBz'

print (regex.sub(r'(.)(?<!\1)', r'(\g<0>)', test))
## xAAAAAyBBBBz

print (regex.sub(r'(.)(.)(?<!\1)', r'(\g<0>)', test))
## (xA)AAA(Ay)BBB(Bz)

请注意,与 pcre 不同,regex 还允许可变宽度后视:

print (regex.sub(r'(.)(?<![A-Z]+)', r'(\g<0>)', test))
## (x)AAAAA(y)BBBB(z)

最终,regex 将包含在标准库中,如 PEP 411 中所述.

最佳答案

这看起来确实像是 Python re 模块中的一个限制(说“错误”的好方法,正如我从与 Microsoft 的支持电话中了解到的那样)。

我猜这与 Python 不支持可变长度的回顾断言这一事实​​有关,但它不够聪明,无法弄清楚 \1 将始终是固定长度的。为什么它在编译正则表达式时不提示这个,我不能说。

有趣的是:

>>> print (re.sub(r'.(?<!\0)', r'(\g<0>)', test))
(x)(A)(A)(A)(A)(A)(y)(B)(B)(B)(B)(z)
>>>
>>> re.compile(r'(.*)(?<!\1)') # This should trigger an error but doesn't!
<_sre.SRE_Pattern object at 0x00000000026A89C0>

所以最好不要在 Python 的后向断言中使用反向引用。积极的后视并没有好多少(它在这里也匹配,就好像它是积极的前瞻一样):

>>> print (re.sub(r'(.)(?<=\1)', r'(\g<0>)', test))
x(A)(A)(A)(A)Ay(B)(B)(B)Bz

我什至猜不到这里发生了什么:

>>> print (re.sub(r'(.+)(?<=\1)', r'(\g<0>)', test))
x(AA)(A)(A)Ay(BB)(B)Bz

关于python - 不可能的反向引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10279055/

相关文章:

python - 如何从函数python返回一个int值

python - 在 Python 中测试抽象类

javascript - 使用正则表达式从正文元素中选择单个文本字符

php - mysql 正则表达式构建

python - 停留在下一个字母生成器——Python 3

python - Tkinter 将背景图像调整为窗口大小

python - 是否可以装饰类属性

python - 如何在 OS X 上安装 python 3

python - flask-peewee 可以迁移吗?

php - 用逗号和换行符在 php 中拆分字符串