Python正则表达式分割段落

6

如何编写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个\n的段落换行。

4个回答

6

很遗憾,没有一种好的方式来写出“空格但不换行”的效果。

我认为你能做的最好的办法就是使用 x 修饰符添加一些空格,并尽量减少丑陋的因素,但这是有问题的:(?x) (?: [ \t\r\f\v]*? \n ){2} [ \t\r\f\v]*?

你也可以尝试创建一个子规则仅用于字符类,并将其插入三次。


3

这不是一个正则表达式,但它确实非常优雅:

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 Cookbook” ;-)


简洁的解决方案。str_isspace是什么? - Brian M. Hunt
一个笔误 :-) 你应该读取 str.isspace,它是字符串对象的 isspace() 方法。它将被调用来确定某个字符是否为空格,并根据此分组对象。我已经修复了它。 - Bite code

2
你可能正在尝试推断纯文本文档的结构,就像 docutils 所做的那样。
你可以使用 Docutils 解析器 而不是自己编写。

1
几乎相同,但使用非贪婪量词并利用空格序列。
\s*?\n\s*?\n\s*?

这会导致示例2失败,因为\s包括\n。 - nosklo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接