Как сопоставить абзац с помощью регулярного выражения

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

Пример текста:

Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum. 

Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit amet.

Ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod
tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At
vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren,
no sea takimata sanctus est Lorem ipsum dolor sit amet.

В этом примере я хотел бы отдельно сопоставить все абзацы, начинающиеся с Lorem, Stet и Ipsum соответственно (без пустых строк). Кто-нибудь знает, как это сделать?


person Chiel ten Brinke    schedule 02.09.2013    source источник
comment
Есть ли причина, по которой вы хотите сделать это с помощью регулярных выражений? Для чего-то столь же простого, как разделение абзацев с разделителями с двумя символами новой строки, вы можете просто использовать paragraph.split('\n\n')   -  person Tim Wakeham    schedule 02.09.2013
comment
Меня интересуют начальная и конечная позиции абзацев, а не сами строки. Я должен был упомянуть об этом.   -  person Chiel ten Brinke    schedule 02.09.2013


Ответы (5)


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

paragraphs = re.split(r"\n\n", DATA)

Редактировать. Чтобы зафиксировать абзацы как совпадения, чтобы вы могли получить их начальную и конечную точки, сделайте следующее:

for match in re.finditer(r'(?s)((?:[^\n][\n]?)+)', DATA):
   print match.start(), match.end()

# Prints:
# 0 214
# 215 298
# 299 589
person RichieHindle    schedule 02.09.2013
comment
Как я могу использовать это, чтобы получить объект соответствия? - person Chiel ten Brinke; 02.09.2013

Использование разделения — это один из способов, вы можете сделать это с помощью регулярного выражения также следующим образом:

paragraphs = re.search('(.+?\n\n|.+?$)',TEXT,re.DOTALL)

.+? - это ленивое совпадение, оно будет соответствовать самой короткой подстроке, которая делает соответствие всему регулярному выражению. В противном случае он будет соответствовать всей строке.

Итак, в основном здесь мы хотим найти последовательность символов (.+?), которая заканчивается пустой строкой (\n\n) или концом строки ($). Флаг re.DOTALL заставляет точку также соответствовать новой строке (мы также хотим сопоставить абзац, состоящий из трех строк без пустых строк внутри)

person justhalf    schedule 02.09.2013
comment
Спасибо за Ваш ответ. Однако обратите внимание, что этот шаблон также соответствует пустым строкам, что неверно. - person Chiel ten Brinke; 02.09.2013

Что такое символ новой строки? Предположим, что символ новой строки '\r\n', если вы хотите сопоставить абзацы, начинающиеся с Lorem, вы можете сделать так:

pattern = re.compile('\r\nLorem.*\r\n')
str = '...'    # your source text
matchlist = re.findall(pattern, str)

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

person Kill Console    schedule 02.09.2013
comment
Символ новой строки в python обычно \n. И ваша схема не работает. - person Chiel ten Brinke; 02.09.2013
comment
Жаль, что я сделал ошибку. Вы можете попробовать это: p = re.compile('^Lorem.*\n') matchlist = re.findall(p,s) Тогда вы получите список абзацев, начинающихся с Lorem - person Kill Console; 11.09.2013

Пытаться

^(.+?)\n\s*\n

or

^(.+?)\r\n\s*\r\n

только не забудьте добавить дополнительную новую строку в конце текста

person Ceyhun Mamedov    schedule 01.02.2014

я попытался использовать рекомендуемый RegEx с механизмом Java RegEx по умолчанию. Это несколько раз вызывало StackOverflowException, поэтому в конце концов я переписал RegEx и еще немного оптимизировал его.

Так что это отлично работает для меня в Java:

(?s)(.*?[^\:\-\,])(?:$|\n{2,})

Это также обрабатывает конец документа без новых строк и пытается объединить строки, которые заканчиваются на «:», «-» или «,», в следующий абзац.

И чтобы избежать того, что конечные пробелы (пробелы или вкладки) нарушают описанную выше функцию, я удаляю их раньше с помощью следующего регулярного выражения:

(?m)[[:blank:]]+$
person wobu    schedule 06.08.2014