Регулярные выражения Python с более чем 100 группами? - PullRequest
21 голосов
/ 26 января 2009

Есть ли способ преодолеть ограничение в 100 групп для регулярных выражений в Python? Кроме того, кто-то может объяснить, почему существует ограничение.

Ответы [ 11 ]

10 голосов
/ 26 января 2009

Существует ограничение, поскольку для эффективного хранения конечного автомата потребуется слишком много памяти. Я бы сказал, что если у вас в группе более 100 групп, что-то не так в самой программе или в том, как вы их используете. Может быть, вам нужно разделить вход и работать на более мелкие куски или что-то.

8 голосов
/ 18 января 2013

Я обнаружил, что самый простой способ был

import regex as re

вместо

import re

По умолчанию _MAXCACHE для регулярных выражений - 500 вместо 100, я полагаю. Это одна из многих причин, по которым я нахожу регулярное выражение лучшим модулем, чем re.

6 голосов
/ 02 декабря 2015

Я сомневаюсь, что вам действительно нужно обработать 100 именованных групп с помощью следующих команд или использовать его в regexp команде замены. Это было бы совершенно непрактично. Если вам просто нужны группы, чтобы выразить расширенные условия в regexp, вы можете использовать группы без группировки.

(?:word1|word2)(?:word3|word4)

и т.д.. Возможны сложные сценарии, включающие вложенные группы. Для групп, не входящих в группу, нет ограничений.

6 голосов
/ 29 мая 2012

Если я не ошибаюсь, «новый» модуль regex (в настоящее время сторонний, но в конечном итоге предназначен для замены модуля re в stdlib) не имеет этого ограничения, так что вы могли бы дать это попытка.

5 голосов
/ 27 января 2009

Я не уверен, что именно вы делаете, но попробуйте использовать одну группу с большим количеством предложений OR внутри ... так что (this) | (that) становится (this | that). Вы можете сделать умные вещи с результатами, передав функцию, которая делает что-то с конкретным словом, которое соответствует:

 newContents, num = cregex.subn(lambda m: replacements[m.string[m.start():m.end()]], contents)

Если вам действительно нужно так много групп, вам, вероятно, придется делать это поэтапно ... один проход для дюжины больших групп, затем другой проход в каждой из этих групп для получения всех необходимых деталей.

3 голосов
/ 26 января 2009

Во-первых, как уже говорили другие, вероятно, есть хорошие альтернативы использованию 100 групп. Метод re.findall может быть полезным для начала. Если вам действительно нужно более 100 групп, единственный обходной путь, который я вижу, - это модификация основного кода Python.

В [python-install-dir]/lib/sre_compile.py просто измените функцию compile(), удалив следующие строки:

# in lib/sre_compile.py
if pattern.groups > 100:
    raise AssertionError(
        "sorry, but this version only supports 100 named groups"
        )

Для немного более гибкой версии просто определите константу в верхней части модуля sre_compile, и приведенная выше строка сравнивается с этой константой вместо 100.

Как ни странно, в (Python 2.5) источнике есть комментарий, указывающий, что ограничение на 100 групп планируется удалить в будущих версиях.

0 голосов
/ 15 мая 2019

Я обнаружил, что Python 3 не имеет этого ограничения, тогда как тот же код, запущенный в последних 2.7, отображает эту ошибку.

0 голосов
/ 23 октября 2014

Когда я столкнулся с этим, у меня был действительно сложный паттерн, который на самом деле был составлен из набора высокоуровневых паттернов, объединенных операционными операциями, например:

pattern_string = u"pattern1|" \
    u"pattern2|" \
    u"patternN"
pattern = re.compile(pattern_string, re.UNICODE)

for match in pattern.finditer(string_to_search):
    pass # Extract data from the groups in the match.

В качестве обходного пути я превратил шаблон в список и использовал этот список следующим образом:

pattern_strings = [
    u"pattern1",
    u"pattern2",
    u"patternN",
]
patterns = [re.compile(pattern_string, re.UNICODE) for pattern_string in pattern_strings]

for pattern in patterns:
    for match in pattern.finditer(string_to_search):
        pass # Extract data from the groups in the match.
    string_to_search = pattern.sub(u"", string_to_search)
0 голосов
/ 19 ноября 2012

Очень легко устранить эту ошибку: Откройте класс re, и вы увидите эту константу _MAXCACHE = 100. Например, измените значение на 1000 и выполните тест.

0 голосов
/ 26 мая 2010

в моем случае у меня есть словарь из n слов, и я хочу создать одно регулярное выражение, которое соответствует всем им ... т.е. если мой словарь равен

hello
goodbye

моим регулярным выражением будет: (^|\s)hello($|\s)|(^|\s)goodbye($|\s) ... это единственный способ сделать это, и он отлично работает на небольших словарях, но когда у вас больше 50 слов слова, хорошо ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...