Regex для части многострочного текста, который включает в себя все виды символов, включая символы новой строки, @, ^, ', "и т. Д. - PullRequest
0 голосов
/ 21 апреля 2020

У меня большой текст, который определяется в подразделе, разделенном на начало и конец. Я хочу извлечь текст между неизменными, а также извлечь имя части в тексте. Я терплю неудачу, так как я использовал. + В своем регулярном выражении, я всегда получаю полный текст. Мне также пришлось извлечь имя детали с помощью другого трюка, так как я не смог поймать его в именованной группе. Поэтому я строю строку с именем в качестве входных данных для регулярного выражения, но все равно это не удается, так как. + Является жадным и захватывает весь текст.

Мой неудачный регулярное выражение:

regex_string = '^!!\sSTART\s' + partname + '\s!!(?P<part_text>.*)'
REGEXP_CONTEXT_CONFIG = re.compile(regex_string, re.DOTALL)

Тест текст для захвата:

!! START goblin !!
text to capture
that is multiline 
and contains all sort 
of special chars 
!! END goblin !!

!! START berta !!
text to capture
that is multiline 
and contains all sort 
of special chars 
!! END berta !!

!! START vlad !!
text to capture
that is multiline 
and contains all sort 
of special chars 
!! END Vlad !!

Я пытаюсь заархивировать это регулярное выражение, которое фиксирует имя части и часть включенного текста в двух именованных группах.

Ответы [ 3 ]

0 голосов
/ 21 апреля 2020

Есть несколько проблем с вашим регулярным выражением:

  • нет конечного маркера

  • жадные рисунки можно сделать нежадными, если знак вопроса после них: .*? или .+?

  • вам необходимо использовать re.MULTILINE, в противном случае ^ соответствует только в начале полного текста (но не в начало каждой строки).

  • Я поместил 1, 2 или 3 в тексте примера, иначе вы все равно не увидите, было ли найдено правильное соответствие


text = """
!! START goblin !!
text 1 to capture
that is multiline
and contains all sort
of special chars
!! END goblin !!

!! START berta !!
text 2 to capture
that is multiline
and contains all sort
of special chars
!! END berta !!

!! START vlad !!
text 3 to capture
that is multiline
and contains all sort
of special chars
!! END Vlad !!
"""

import re

partname = "berta"
pattern = '^!!\sSTART\s' + partname + '\s!!(?P<part_text>.*)!!\sEND\s' + partname + '\s!!'
regex = re.compile(pattern, re.DOTALL|re.MULTILINE)
match = regex.search(text)
print(match.group('part_text'))

Вывод:

text 2 to capture
that is multiline
and contains all sort
of special chars

(вам может потребоваться немного поиграть, чтобы избавиться от пустых строк новой строки. Или просто используйте match.group('part_text').strip()).

0 голосов
/ 21 апреля 2020

Я думаю, что нашел рабочие решения с помощью комментариев и ответов здесь. Большое спасибо!

re.compile('^!!\sSTART\s(?P<part_name>\w+)\s!!(?P<part_text>.*?)!!\sEND\s\w+\s!!', re.DOTALL|re.MULTILINE)
0 голосов
/ 21 апреля 2020

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

(?smi)^!! START (?P<part_name>goblin|berta|vlad) !!(?P<part_text>.*?)!! END (?P=part_name) !!

См. Демонстрационную версию регулярных выражений .

Подробности

  • (?smi) - точка теперь соответствует символу новой строки (s), ^ также соответствует началу строки (m), а шаблон не учитывает регистр (i)
  • ^ - начало строки
  • !! START - буквенная строка
  • (?P<part_name>goblin|berta|vlad) - группа "part_name", захватывающая одно из имен
  • !! - буквальный текст
  • (?P<part_text>.*?) - группа "part_text": любые 0+ символов, как можно меньше
  • !! END - буквенная строка
  • (?P=part_name) - тот же текст, что и в группе "part_name"
  • !! - буквальный текст.

В коде используйте

partnames = ['goblin', 'berta', 'vlad']
regex_string = '^!! START (?P<part_name>{}) !!(?P<part_text>.*?)!! END (?P=part_name) !!'.format("|".join(partnames))
REGEXP_CONTEXT_CONFIG = re.compile(regex_string, re.DOTALL | re.M| re.I)
print( REGEXP_CONTEXT_CONFIG.findall(text) )
# => [('goblin', '\ntext to capture\nthat is multiline \nand contains all sort \nof special chars \n'), ('berta', '\ntext to capture\nthat is multiline \nand contains all sort \nof special chars \n'), ('vlad', '\ntext to capture\nthat is multiline \nand contains all sort \nof special chars \n')]

См. Демонстрационную версию Python . Вы можете убрать начальные / конечные пробелы из текстов деталей позже.

...