Regex для захвата всех вхождений текста, разделенных последовательностью символов - PullRequest
1 голос
/ 08 марта 2011

Можно ли построить регулярное выражение, которое фиксирует все вхождения текста, разделенного последовательностью символов? Другими словами, я ищу эквивалент стандартного .split() метода.

Я не могу использовать split(), потому что регулярное выражение используется при указании URL-маршрутов для веб-приложения Tornado. Например:

handlers = [
    (r'/posts/([0-9a-zA-Z_\-]+)', PostsHandler),
]

Такое регулярное выражение удобно использовать при указании URL-маршрутов для веб-приложений, созданных поверх Tornado, Django или любой другой веб-среды, в которой реализован шаблон Routes. В частности, для разбора пути URL неизвестной длины в список аргументов.

Пока мне удалось придумать следующее регулярное выражение:

/^\/posts(?:\/([a-zA-Z0-9_\-]+))+/

К сожалению, хотя выражение соответствует /posts/show/some-slug/15, оно возвращает только последнюю подходящую группу (15) вместо ['show', 'some-slug', '15'].

Я хочу достичь:

  • /posts/edit/15/ => ['edit', '15']
  • /posts/edit/15 => ['edit', '15']
  • /posts/2010/15/11 => ['2010', '15', '11']

Ответы [ 4 ]

5 голосов
/ 02 апреля 2012

Нет способа сопоставить неограниченное количество захватов в Python.Каждая группа захвата может захватывать только одно совпадение, и по определению в Python она захватывает последнее совпадение.В частности, см. Документацию по MatchObject.group:

http://docs.python.org/library/re.html#re.MatchObject.group

В частности, следующий текст объясняет ограничение групп захвата:

Если группапоследнее совпадение, содержащееся в части шаблона, которая совпадает несколько раз, возвращается.

Таким образом, единственный способ получить несколько совпадений - это установить верхнюю границу для общего числа групп захвата.Таким образом, что-то вроде следующего (непроверенного) будет соответствовать до пяти захватов:

/^\/posts\/([\w-]+)(?:\/([\w-]+)(?:\/([\w-]+)(?:\/([\w-]+)(?:\/([\w-])+)?)?)?)?

Вы можете потенциально построить строку для регулярного выражения, динамически следуя предыдущему шаблону, но в любом случае это будет довольно ужасно.

1 голос
/ 08 марта 2011

Чтобы поймать все совпадения с регулярным выражением, вы используете

[ match.groups(....) for match in  pattern.finditer(the_string) ]

Чтобы разделить по шаблону, вы используете:

re.split()

очень интересная функция

1 голос
/ 08 марта 2011

Вы пробовали: str.split('/')? Это должно делать именно то, что вы хотите (если я правильно понимаю). Есть ли причина, по которой это должно быть регулярное выражение?

0 голосов
/ 08 марта 2011

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

/^\/posts(?:\/([a-zA-Z0-9_\-]+))+/g

Кроме того, многие языки имеют функцию split на основе регулярных выражений. Учтите, что, если она доступна, или просто старую старую функцию разделения строк (которая действительно больше похожа на нужный вам инструмент).

...