2017-02-10 11 views
0

Я ищу что-то похожее на механизм регулярных выражений, но позволяет полностью перекрывать результаты и позволяет манипулировать внутренним «курсором», когда движок возвращает совпадения ,Регулярно/совпадающий движок с полностью перекрывающимися результатами и манипуляцией «курсором»

нормальный регулярное выражение так:

Скажем, у вас нормальное регулярное выражение с различными «альтернатив»: item1|item2|item3, и вы используете либо findall или finditer, чтобы получить все матчи. В определенной позиции во входной строке двигатель может соответствовать любым из этих альтернатив. После обнаружения курсор продвигается к индексу сразу после окончания матча и продолжает искать любую альтернативу. Даже если два или более из этих альтернатив, возможно, соответствуют строке в позиции начального курсора, только один возвращаются:

import re 
input_string = 'foobar' 
compiled = re.compile('foobar|foo|bar') 
compiled.findall(input_string) 

# 'foobar' 

То, что я хочу (1):

Я хочу, чтобы они все были вернулся. Как так:

import muchneededregexthing 
input_string = 'foobar' 
compiled = muchneededregexthing.compile('foobar|foo|bar') 
searcher = compiled.create_searcher(input_string) 
while not searcher.reached_end(): 
    match = searcher.search() # increments searcher's internal cursor 
           # to after the end of the match 
    print(match.string, match.span()) 

# foobar (0,6) 
# foo (0,3) 
# bar (3,6) 

То, что я также хочу (2):

Я хочу, чтобы иметь возможность изменить курсор искателя, так что я могу манипулировать результатами в соответствии с тем, что происходит во время выполнения (» foobar ', и «foo» и «bar» отдельно не имеют значения).

import muchneededregexthing 
input_string = 'foobarkitten' 
compiled = muchneededregexthing.compile('foobar|foo|bar|kitten') 
searcher = compiled.create_searcher(input_string) 
while not searcher.reached_end(): 
    match = searcher.search() # increments searcher's internal cursor 
           # to after the end of the match 
    print(match.string, match.span()) 
    if match.string == 'foobar': 
     searcher.advance_cursor(match.end()) 

# foobar (0,6) 
# kitten (6,12) 

То, что я не могу использовать (скорее всего):

  • str.find: Мне нужно регулярное выражение вещь для разметки (уценки/вики/и т.д.) парсера. В любое время, возможно, придется искать много разных элементов. Использование str.find Мне нужно будет искать весь документ с каждым элементом, который поддерживает разметка. Язык слишком сложный, чтобы разделить документ на куски, такие как «кусок заголовка», «параграф абзаца» и т. Д.

  • : Если я не могу поддержать то, что мне нужно, я не могу использовать его по следующей причине: regexes ограничены, вы не можете подобрать что угодно. Однако их свойства полезны для таких случаев, как мой. Я планирую совпадение в два этапа: регулярное выражение обеспечивает возможное соответствие элемента. Затем следует использовать умную функцию/метод, соответствует ли совпадению . Если да, то большой, продвигаемый курсор. Если нет, завинтите foobar и дайте foo и bar шанс самостоятельно.

Идеи приветствуются. Я абсолютно уверен, что мне нужны указанные функции. Моя лучшая идея заключается в том, чтобы написать собственный модуль muchneededregexthing с поддержкой большей части синтаксиса регулярных выражений на C/C++, поэтому не бойтесь, что я буду игнорировать вашу идею как надуманную.

Редактировать 1: запрос пример разметки:

элементов разметки, и поэтому маркеры, которые должны быть согласованы, определены и приведены в с помощью плагинов.Поэтому структура не содержит никакой разметки. Я мог бы просто сопоставить токен плагина с регулярным выражением и сделать с ним, но я хочу, по крайней мере, изучить параметры и попытаться разрешить большее количество маркеров разметки, чем то, что можно было бы поддерживать с помощью регулярного выражения. Например, как бы соответствовать string:number, если бы их отношение состояло в том, что число должно быть числом численного представления строки? a:0 - действительный токен, но a:1 нет. b:1 есть, однако, и поэтому bc:28 (1 * 26 + 2 * 1).

В этом примере плагин может содержать регулярное выражение, такое как ([a-z]{1,5})([0-9]{1,5}). Затем алгоритм передает соответствие специальной функции, которая вычисляет численное значение первой группы и сравнивает ее со значением второй группы. Если эти значения совпадают, то плагин будет обрабатывать эту часть документа. Если нет, он возвращается и делается попытка сделать другой плагин обработчиком этого индекса в документе.

+0

Поведение по умолчанию совпадающего соответствия - это перемещение курсора по одной позиции после каждого совпадения. Если не разрешено продвигать хотя бы одну позицию, она вводит бесконечный цикл. Регулярное выражение исправлено. Пример '(? = (O + | foo))' в строке 'fooooo' находит 5 совпадений. Кроме того, один символ существует в позиции за раз, поэтому только регулярное выражение может быть переменным. То есть. _item_'X' может быть только _X_ и никогда Y. Но регулярное выражение фиксируется в состоянии, поэтому оно никогда не может меняться. Таким образом, продвижение позиции. – sln

+0

Вы могли бы использовать несколько регулярных выражений, чтобы отсканировать одну позицию. Но вы должны контролировать это, установив регулярное выражение и установив позицию в строке. Это одно действие. – sln

+0

Можете ли вы привести пример своей уценки? Вероятно, это можно решить с помощью регулярного выражения или рекурсивного синтаксического анализатора. – fafl

ответ

0

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

Если pattern представляет собой скомпилированное регулярное выражение, то pattern.search(str, start) будет искать совпадения, начиная с start и pattern.search(str, start, length) будет искать совпадения, начиная с start длиной не более length.

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

+0

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