Python正则表达式源字符串长度

4 投票
2 回答
3869 浏览
提问于 2025-04-15 17:36

在Python的正则表达式中,

re.compile("x"*50000)

我遇到了一个错误:OverflowError: regular expression code size limit exceeded

但是下面这个没有报错,却让我的电脑CPU使用率飙到100%,而且运行了一分钟

>>> re.compile(".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000)
<_sre.SRE_Pattern object at 0x03FB0020>

这是正常现象吗?

我是不是可以认为,".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000"x"*50000

我是在Python 2.6和Win32上测试的

更新 1

看起来".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000可以简化为.*?

那这个呢?

re.compile(".*?x"*50000)

这个是可以编译的,如果它也能简化为".*?x",那么它应该能匹配字符串"abcx"或者单独的"x",但实际上并没有匹配。

所以,我是不是漏掉了什么?

更新 2

我想知道的不是正则表达式源字符串的最大限制,我想了解为什么"x"*50000".*?x"*50000

这对我来说没有意义,所以我想知道,是不是在溢出检查上有什么遗漏,还是说这样是正常的,或者确实是溢出了什么?

任何提示或意见都非常感谢。

2 个回答

1

你是想匹配50000个"x"对吧??? 如果是这样的话,有一种不使用正则表达式的方法。

if "x"*50000 in mystring:
    print "found"

如果你想用正则表达式匹配50000个"x",可以使用范围的方式。

>>> pat=re.compile("x{50000}")
>>> pat.search(s)
<_sre.SRE_Match object at 0xb8057a30>

在我的系统上,最大长度是65535。

>>> pat=re.compile("x{65536}")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/re.py", line 188, in compile
    return _compile(pattern, flags)
  File "/usr/lib/python2.6/re.py", line 241, in _compile
    p = sre_compile.compile(pattern, flags)
  File "/usr/lib/python2.6/sre_compile.py", line 529, in compile
    groupindex, indexgroup
RuntimeError: invalid SRE code
>>> pat=re.compile("x{65535}")
>>>

不过我不知道在Python中有没有什么方法可以用来增加这个限制。

6

这段话的意思是,".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000 可以简化成 ".*?",而 "x"*50000 则需要在正则表达式引擎中生成50000个节点(或者类似的结构)。

编辑:好吧,我错了。其实并没有那么聪明。"x"*50000 失败的原因是因为它生成了一个很长的项目,而 ".*?x"*50000 则生成了很多小项目。每个“代码项”的大小是有限制的。如果能以某种方式拆分字符串而不改变正则表达式的意思,那就可以了,但我想不出有什么办法可以做到这一点。

撰写回答