регулярное выражение python для разделения абзацев

Как написать регулярное выражение для использования в Python для разделения абзацев?

Абзац определяется двумя разрывами строки (\ n). Но можно иметь любое количество пробелов / табуляции вместе с разрывами строк, и это все равно следует рассматривать как абзац.

Я использую python, поэтому решение может использовать расширенный синтаксис регулярных выражений python . (может использовать (?P...) материал)

Примеры:

the_str = 'paragraph1\n\nparagraph2'
# splitting should yield ['paragraph1', 'paragraph2']

the_str = 'p1\n\t\np2\t\n\tstill p2\t   \n     \n\tp3'
# should yield ['p1', 'p2\t\n\tstill p2', 'p3']

the_str = 'p1\n\n\n\tp2'
# should yield ['p1', '\n\tp2']

Лучшее, что я мог найти, это: r'[ \t\r\f\v]*\n[ \t\r\f\v]*\n[ \t\r\f\v]*', т.е.

import re
paragraphs = re.split(r'[ \t\r\f\v]*\n[ \t\r\f\v]*\n[ \t\r\f\v]*', the_str)

но это уродливо. Что-нибудь лучше?

ИЗМЕНИТЬ:

Предложения отклонены:

r'\s*?\n\s*?\n\s*?' -> Это приведет к сбою примеров 2 и 3, так как \s включает \n, поэтому допускается разрыв абзаца с более чем 2 \ns.


person nosklo    schedule 22.09.2008    source источник


Ответы (5)


К сожалению, нет хорошего способа написать «пробел, но не новую строку».

Я думаю, лучшее, что вы можете сделать, - это добавить немного места с помощью модификатора x и попытаться немного исключить уродство, но это сомнительно: (?x) (?: [ \t\r\f\v]*? \n ){2} [ \t\r\f\v]*?

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

person Eevee    schedule 22.09.2008

Вы пытаетесь определить структуру документа простым тестом? Вы делаете то, что делает Docutils?

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

person S.Lott    schedule 22.09.2008

Не регулярное выражение, но очень элегантное:

from itertools import groupby

def paragraph(lines) :
    for group_separator, line_iteration in groupby(lines.splitlines(True), key = str.isspace) :
        if not group_separator :
            yield ''.join(line_iteration)

for p in paragraph('p1\n\t\np2\t\n\tstill p2\t   \n     \n\tp'): 
    print repr(p)

'p1\n'
'p2\t\n\tstill p2\t   \n'
'\tp3'

Разумеется, вам решать, как вырезать вывод по мере необходимости.

На основе знаменитой "Поваренной книги Python" ;-)

person e-satis    schedule 23.09.2008
comment
Аккуратное решение. Что str_isspace? - person Brian M. Hunt; 01.11.2011
comment
Опечатка :-) Вы должны прочитать str.isspace, который является методом isspace () из строки объекта. Он будет вызываться, чтобы определить, является ли что-то пробелом, и сгруппирует объект в соответствии с этим. Я починил это. - person e-satis; 02.11.2011

Почти то же самое, но с использованием нежадных квантификаторов и использования последовательности пробелов.

\s*?\n\s*?\n\s*?
person Joseph Bui    schedule 22.09.2008
comment
это приведет к сбою примера 2, потому что \ s включает \ n. - person nosklo; 22.09.2008

К вашему сведению: я только что написал 2 решения для этого типа проблемы в другом потоке. Во-первых, с использованием регулярных выражений, как указано здесь, а во-вторых, с использованием подхода конечного автомата, который передает входные данные по одной строке за раз:

https://stackoverflow.com/a/64863601/5201675

person traal    schedule 16.11.2020