【发布时间】:2016-10-23 04:20:18
【问题描述】:
我有一堆带有硬换行的文本文件(即大约 80 个字符的新行)。我想撤消它并将所有这些句子连接在一起,但在它们是新章节或段落的地方保留新行。
即当且仅当以下字符不是另一个'\n'时,我想用''替换'\n'
以下 python 代码可以满足我的需求,但效率不高,我宁愿使用 regex 和/或 sed 来实现。
s = open(filename, 'r').read()
p = s.split('\n\n') # split into paragraphs
p = [x.replace('\n', ' ') for x in p] # iterate all paragraphs, replace \n
s2 = '\n\n'.join(p) # join paragraphs back together
例如
Lorem ipsum dolor sit amet, consectetur adipiscing
elit. Vivamus porta dui quis aliquet interdum. Sed
in pellentesque libero. Quisque tempus nisl nec
nisl condimentum ullamcorper.
Mauris vulputate nibh nec ipsum mattis rutrum.
Nunc nec tristique magna, non sagittis lacus.
Aliquam id urna lectus.
Maecenas volutpat libero quis erat mollis, et
aliquet purus dignissim. Sed faucibus, lectus in
auctor ornare, dolor libero ultrices sem, vel
iaculis ex nulla quis lacus.
应该变成:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus porta dui quis aliquet interdum. Sed in pellentesque libero. Quisque tempus nisl nec nisl condimentum ullamcorper.
Mauris vulputate nibh nec ipsum mattis rutrum. Nunc nec tristique magna, non sagittis lacus. Aliquam id urna lectus.
Maecenas volutpat libero quis erat mollis, et aliquet purus dignissim. Sed faucibus, lectus in auctor ornare, dolor libero ultrices sem, vel iaculis ex nulla quis lacus.
更新
我已经在一个 5MB 的文本文件上尝试并计时了下面的 5 种 python 方法。我很惊讶地发现所有 3 种正则表达式方法都比 python 的 split/replace/join 方法慢了一个数量级。
def m1(s):
p = s.split('\n\n') # split into paragraphs
p = [x.replace('\n', ' ') for x in p] # iterate all paragraphs, replace \n
r = '\n\n'.join(p) # join paragraphs back together
return r
def m2(s):
r = re.sub(r"(?<!\n)\n(?!\n)", " ", s)
return r
def m3(s):
p = re.compile(ur'(?<!^)\n(?=\S)', re.MULTILINE)
r = re.sub(p, u" ", s)
return r
def m4(s):
r = "".join(["".join(v) if k else " ".join(map(str.strip, v))+"\n" for k, v in groupby(s, str.isspace)])
return r
def repl(m):
return (' ' if len(m.group(1))==1 else m.group(1)) + m.group(2)
def m5(s):
r = re.sub(r'(\n+)(.)', repl, s)
return r
结果:
np.array( timeit.repeat('r=m1(s)', 'from __main__ import *', repeat=5, number=N) )/N
Out[4]: array([ 0.01343679, 0.0136183 , 0.0153013 , 0.0122381 , 0.01205051])
np.array( timeit.repeat('r=m2(s)', 'from __main__ import *', repeat=5, number=N) )/N
Out[5]: array([ 0.10881839, 0.108728 , 0.10904381, 0.10862441, 0.10867569])
np.array( timeit.repeat('r=m3(s)', 'from __main__ import *', repeat=5, number=N) )/N
Out[6]: array([ 0.1358021 , 0.1352592 , 0.13556101, 0.1357465 , 0.1354876 ])
np.array( timeit.repeat('r=m4(s)', 'from __main__ import *', repeat=5, number=N) )/N
Out[7]: array([ 2.51403842, 2.37821078, 2.4169096 , 2.56688828, 2.36240571])
np.array( timeit.repeat('r=m5(s)', 'from __main__ import *', repeat=5, number=N) )/N
Out[8]: array([ 0.16381941, 0.1616353 , 0.1620033 , 0.1617353 , 0.1615443 ])
【问题讨论】: