Как использовать регулярное ВЫРАЖЕНИЕ с многострочностью

#python #regex

#python #регулярное выражение

Вопрос:

Следующее выражение работает хорошо, извлекая часть data строки, которая начинается со слова, Block за которым следует открытая скобка { , и заканчивается закрывающей скобкой ‘}’:

 data ="""
Somewhere over the rainbow
Way up high 
Block {
 line 1
 line 2
 line 3
}
And the dreams that you dreamed of
Once in a lullaby
"""
regex = re.compile("""(Block {n [^{}]*n}n)""", re.MULTILINE)
result = regex.findall(data)
print result 
  

которое возвращает:

 ['Block {n line 1n line 2n line 3n}n']
  

Но если внутри блочной части строки есть еще одна фигурная скобка, выражение прерывается, возвращая пустой список:

 data ="""
Somewhere over the rainbow
Way up high 
Block {
 line 1
 line 2
 {{}
 line 3
}
And the dreams that you dreamed of
Once in a lullaby
Block {
 line 4
 line 5
 {{
 }
 line 6
}
Somewhere over the rainbow
Blue birds fly
And the dreams that you dreamed of
Dreams really do come true ooh oh
"""
  

Как изменить это выражение регулярного выражения, чтобы оно игнорировало скобки, находящиеся внутри блоков, и при этом каждый блок возвращался как отдельный объект в result списке (чтобы к каждому блоку можно было обращаться отдельно)?

Комментарии:

1. На самом деле [^{}]* предотвращает сопоставление любой открывающей фигурной скобки. Обратите внимание, что МНОГОСТРОЧНЫЙ флаг — это не то, что вы думаете. (это не для сопоставления строк, которые распространяются на несколько строк, это только изменяет значение якорей ^ и $ . Чтобы точка соответствовала новым строкам, флаг равен DOTALL)

2. Поскольку вы отредактировали свой вопрос: эта проблема не может быть решена с помощью модуля re, вам нужен модуль regex , который обрабатывает рекурсию. Обратите внимание, что вам нужно выбрать поведение по умолчанию для неопределенных случаев.

Ответ №1:

Разве это не сработало бы?

regex = re.compile("""(Block {n [^}]*n}n)""", re.MULTILINE)

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

Комментарии:

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

2. Что конкретно закрывает блок? n}n ?

3. Да, блок всегда закрывается с n}n . И это всегда начинается с Block {n

Ответ №2:

Я бы посоветовал вам использовать:

 (Block ?{n ?[^$] ?n}n)
  

Поскольку python соответствует жадности, мы используем ? быть нежадным.

У меня хорошо сработало. Кроме того, я бы рекомендовал вам использовать https://regex101.com /

С наилучшими пожеланиями

Комментарии:

1. Спасибо за ответ! Но ваше выражение возвращает оба блока как единый объект в списке. Он учитывает только первую и последнюю скобки.

2. С вашими изменениями это работает хорошо: (Блокировать? {n ?[^$] ?n}n)