Многострочная жадная группа регулярных выражений Python

Я пытаюсь проанализировать следующий текст примера в Python:

Foo 1
foo1Text

Bar 
bar1Text

Baz 
baz1Text

Foo 2
foo2Text

Bar 
bar2Text

Baz 
baz2Text

# and so on up to Foo/Bar/Baz N

Теперь регулярное выражение, которое я использую:

([\S ]+)(\n*)([\s\S]*?)Bar([\s\S]*?)Baz([\s\S]*?)

Теперь я хотел бы извлечь текст, относящийся к foo/bar/baz. Однако с ленивым квалификатором в конце регулярного выражения ? выражение обрывается и пропускает baz2text. И наоборот, если сделать его жадным, то это соответствует всему остальному как части последней группы.

Я бы предпочел не использовать числовой квалификатор, если это возможно, и в целом сопоставлять вещи на основе:

{title}
{stuff about title}

Bar
{stuff about Bar}

Baz
{stuff about Baz}

Таким образом, я могу перебирать каждое совпадение и соответственно извлекать группы. Обратите внимание, я не сформулировал это для извлечения конкретного вывода. Меня больше всего интересует получение групп регулярных выражений, чтобы они представляли: {title}, {stuff about title}, {stuff about bar}, {stuff about Baz}

Я возился с regex101, чтобы посмотреть, смогу ли я определить правильное заклинание, но безрезультатно.

Это одна из тех задач, которую достаточно легко решить вручную. Но тогда я бы ничему не научился! :) Я хотел бы знать, есть ли какой-то более чистый механизм / стратегия, которую я должен использовать здесь.

Спасибо большое


person thetwan    schedule 13.03.2018    source источник
comment
Непонятно, какой должен быть вывод.   -  person revo    schedule 13.03.2018
comment
На самом деле нет вывода как такового. Меня больше интересует продвижение групп: {название}, {материал о названии}, {материал о Баре} и {материал о Базе}. Обновлю вопрос, чтобы он был более ясным.   -  person thetwan    schedule 13.03.2018
comment
Я не уверен, где должен останавливаться каждый блок. Пожалуйста, проверьте эту демонстрацию regex101.com/r/b8PPoL/1   -  person revo    schedule 14.03.2018
comment
Я начинаю думать так же. Возможно, я задал невозможный вопрос. Как можно отличить новый {title} от некоторого элемента многострочного текста из {stuff about Baz}? Без дискриминатора ничего не скажешь. В моем случае существует неявная иерархия, которую я не могу здесь разглашать, но я считаю, что должен использовать ее здесь. В любом случае, оцените вклад!   -  person thetwan    schedule 14.03.2018


Ответы (1)


Если вы знаете, что Foo является следующей группой после Baz, то вам нужен lookahead: ([\S ]+)(\n*)([\s\S]*?)Bar([\s\S]*?)Baz([\s\S]*?)(?=Foo).

Упреждения — это утверждения с нулевой шириной, поэтому они гарантируют, что совпадение следует сразу же, но не изменяет текущую позицию.

person Brian Stephens    schedule 13.03.2018
comment
Это работает с фиксированным именем, например Foo, но не с произвольным заголовком. Хотя спасибо за ссылку на lookahead. Другой способ посмотреть на это я не рассматривал. Буду экспериментировать с регулярными выражениями в упреждающем выражении. - person thetwan; 13.03.2018