Regex для поиска текстов между вложенными скобками

1

У меня очень длинная строка с вложенными циклами. Я хочу извлечь шаблон в этом.

String_Text:

some random texts......
........................
........................
{{info .................
.....texts..............
...{{ some text }}...... // nested parenthesis 1
........................
...{{ some text }}...... // nested parenthesis 2
........................
}} // End of topmost parenthesis
........................
..again some random text
........................
........................ // can also contain {{  }}
......End of string.

Я хочу извлечь весь текст между верхней скобкой, т.е.

Extracted_string:

info .................
.....texts..............
...{{ some text }}...... // nested parenthesis 1
........................
...{{ some text }}...... // nested parenthesis 2
........................

Шаблон:

1.) начинается с { и за ним может следовать любое число {.

2.) После этого может быть любое количество пробелов.

3.) Первое слово после этого обязательно информация.

4.) Извлеките до тех пор, пока этот кронштейн не будет закрыт.

Что до сих пор пробовали:

re.findall(r'\{+[^\S\r\n]*info\s*(.*(?:\r?\n.*)*)\}+')

Я знаю, что это неправильно, так как это происходит, это найти последний экземпляр } в строке. Может ли кто-нибудь помочь мне в извлечении текста между этими скобками? ТИА

  • 1
    Можете ли вы использовать контекст здесь и сопоставить до первого }} которые находятся на отдельной строке? Как re.findall(r'(?sm)^{{[^\S\r\n]*info\s*(.*?)^}}$', s) ?
  • 0
    Вау! Это работает. Большое спасибо! Можете ли вы объяснить мне, как это работает?
Теги:

3 ответа

1
Лучший ответ

Работа вокруг шаблона может быть той, которая соответствует строке, начинающейся с {{info а затем соответствует любым символам 0+ как можно меньше вплоть до строки с помощью }} на ней:

re.findall(r'(?sm)^{{[^\S\r\n]*info\s*(.*?)^}}$', s)

См. Демо-версию regex.

подробности

  • (?sm) - re.DOTALL (теперь . совпадает с символом новой строки) и re.MULTILINE (^ теперь соответствует линии начали и $ соответствуют окончанию линии позиции) флаги
  • ^ - начало строки
  • {{ - a {{ подстрока
  • [^\S\r\n]* - 0+ горизонтальные пробелы
  • info - подстрока
  • \s* - 0+ пробелы
  • (.*?) - Группа 1: любые 0+ символы, как можно меньше
  • ^}}$ - начало строки, }} и конец строки.
3

Вам нужно использовать рекурсивный подход:

{
    ((?:[^{}]|(?R))*)
}

Это поддерживается только новым модулем regex, см. Демонстрацию на regex101.com.

  • 1
    Это может не совпадать, поскольку OP ожидает только извлечения содержимого подстрок {{info...}} . И вы не можете просто добавить info после первого { in {((?:[^{}]|(?R))*)} .
  • 0
    Привет! большое спасибо. Это работает, но соответствует всем {{}} строкам, я этого не хотел. Я даже проголосовал за ваш ответ, но нашел, что ответ Виктора является наиболее подходящим, поэтому я принял его.
0

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

b = 1
i = si = s.index('{')
i += 1
while b:
    if s[i] == '{': b += 1
    elif s[i] == '}': b -=1
    i += 1

ss = s[si:i]

где, с вашей строкой, определенной как: s, дает подстроку, ss, as:

>>> print(ss)
{{info .................
.....texts..............
...{{ some text }}...... // nested parenthesis 1
........................
...{{ some text }}...... // nested parenthesis 2
........................
}}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню