2010-01-04 1 views
4

В Python регулярных выражений,Regular Expression Пайтона Источник Длина строки

re.compile("x"*50000) 

дает мне OverflowError: regular expression code size limit exceeded

но после один не получает какую-либо ошибку, но она попадает 100% CPU, и занимает 1 минуту в моей ПК

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

Это нормально?

Должен ли я предположить, ".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000 короче "x"*50000?

Испытано на Python 2.6, Win32

UPDATE 1:

Похоже, ".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000 можно свести к .*?

Итак, как насчет этого?

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

Он компилируется, и если один может также свести к ".*?x", он должен соответствовать нанизывать "abcx" или "x" в одиночку, но это не соответствует.

Итак, я что-то упустил?

UPDATE 2:

Моя точка не знать максимальный предел регулярных выражений строк источника, я хотел бы знать некоторые причины/концепция "x"*50000 пойманного обработчика переполнения, но не на ".*?x"*50000.

Это не имеет смысла для меня, вот почему.

Это что-то не хватает при проверке переполнения или его просто отлично или что-то действительно переполнено?

Любые советы/мнения будут оценены.

+0

Нет ". *? X" * 5000 не уменьшается до ". *? X" - он сводится к регулярному выражению с 5000 x в, с ". *?" перед каждым x. Вот почему он не соответствует «abcx» или «x» - он будет соответствовать только строке с 5000 x. –

+1

Это напоминает мне, что я ударил максимальную длину PHP для регулярных выражений, когда я попытался преобразовать ABNF для путей SVG в regexp. Итак, ИМХО, ответ был бы полезен. – Boldewyn

+0

@Dave Kirby, спасибо, но его 50000 (50k). Мои исходные вопросы: 're.compile (« x »* 50000)' не компилируется, но 're.compile (". *? X "* 50000)' компилируется. – YOU

ответ

6

Разница заключается в том, что ".*?.*?.*?.*?.*?.*?.*?.*?.*?.*?"*50000 может быть уменьшен до ".*?", а "x"*50000 должен генерировать 50000 узлов в FSM (или аналогичную структуру, используемую движком регулярных выражений).

EDIT: Хорошо, я ошибся. Это не так уж умно. Причина, почему "x"*50000 не удается, но ".*?x"*50000 не означает, что существует ограничение на размер одного «элемента кода». "x"*50000 будет генерировать один длинный элемент, а ".*?x"*50000 будет генерировать много мелких предметов. Если бы вы могли каким-то образом разбить строковый литерал, не изменяя значения регулярного выражения, это сработает, но я не могу придумать, как это сделать.

+0

Спасибо, но как насчет 're.compile (". *? X "* 50000)'? – YOU

+0

Я действительно не знаю о внутренних элементах движка regex Python, поэтому я не уверен. Регулярное выражение должно совпадать с 50000 x с любыми символами между ними. Я не знаю, что такое оптимизация, но вполне вероятно, что он делает что-то особенное в регулярном выражении. FYI, все регулярные выражения работают в Linux. –

+0

Спасибо за информацию о версии linux, я только что проверил функцию _sre.c -> _compile, нет специального кода для окон, поэтому может быть из-за некоторого размера, отличного от 'wchar_t', и/или ваш питон скомпилирован с помощью' Unicode = UCS4' – YOU

1

Вы хотите соответствовать 50000 "x" s, правильно ???если да, то альтернатива без регулярных выражений

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

, если вы хотите, чтобы соответствовать 50000 «х» с помощью регулярных выражений, вы можете использовать диапазон

>>> 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, мы можем использовать, чтобы увеличить этот предел.

+1

+1 Спасибо, но я искал причину, почему для regex – YOU

+0

Спасибо за обновление для кода, но '{65535}' - это предел повторения, который немного отличается от моего. '' x "* 50000' и' "x {50000}' в моем понимании отличается. – YOU

+0

«x» * 50000 производит 50000 x .. в регулярном выражении, если вы положите x {50000}, вы сообщаете движку регулярных выражений для поиска 50000 x также ... Или мне что-то не хватает? Вы должны четко указать, что вы хотите сделать в своем вопросе с примерами ... – ghostdog74