删除Python中不必要的换行符的最有效方法



我想知道如何使用Python来消除文本中不必要的换行符,就像你从古腾堡项目中得到的那样,他们的纯文本文件每70个字符左右用换行符格式化一次。在Tcl中,我可以做一个简单的string map,如下所示:

set newtext [string map "{r} {} {nn} {nn} {nt} {nt} {n} { }" $oldtext]

这将保持由两个换行符(或换行符和制表符)分隔的段落是分开的,但将以一个换行符结束的行放在一起(用空格代替),并删除多余的CR。由于Python没有string map,我还没有找到最有效的方法来转储所有不必要的换行符,尽管我很确定只是按顺序搜索每条换行符并用空格替换它是而不是。如果其他方法都失败了,我可以在Python中评估Tcl表达式,但我想找出做同样事情的最佳Python方法。这里的Python鉴赏家能帮我吗?

与tcl string map最接近的等价物是str.translate,但不幸的是,它只能映射单个字符。因此,有必要使用regexp来获得类似的紧凑示例。这可以通过look-behind/plook-ahead断言来完成,但必须首先替换r

import re
oldtext = """
This would keep paragraphs separated.
This would keep paragraphs separated.
This would keep paragraphs separated.
tThis would keep paragraphs separated.
rWhen, in the course
of human events,
it becomes necessary
rfor one people
"""
newtext = re.sub(r'(?<!n)n(?![nt])', ' ', oldtext.replace('r', ''))

输出:

This would keep paragraphs separated. This would keep paragraphs separated.
This would keep paragraphs separated.
    This would keep paragraphs separated.
When, in the course of human events, it becomes necessary for one people

不过,我怀疑这是否和tcl代码一样有效。

更新

我用古腾堡项目的《战争与和平》电子书(纯文本UTF-8,3.1MB)做了一个小测试。这是我的tcl脚本:

set fp [open "gutenberg.txt" r]
set oldtext [read $fp]
close $fp
set newtext [string map "{r} {} {nn} {nn} {nt} {nt} {n} { }" $oldtext]
puts $newtext

和我的python等价物:

import re
with open('gutenberg.txt') as stream:
    oldtext = stream.read()
    newtext = re.sub(r'(?<!n)n(?![nt])', ' ', oldtext.replace('r', ''))
    print(newtext)

原油性能测试:

$ /usr/bin/time -f '%E' tclsh gutenberg.tcl > output1.txt
0:00.18
$ /usr/bin/time -f '%E' python gutenberg.py > output2.txt
0:00.30

因此,正如预期的那样,tcl版本更加高效。然而,python版本的输出似乎更干净(没有在行的开头插入额外的空格)。

您可以使用正则表达式进行前瞻性搜索:

import re
text = """
...
"""
newtext = re.sub(r"n(?=[^nt])", " ", text)

这将用空格替换任何没有换行符或制表符的新行。

当我想这样做时,我使用以下脚本:

import sys
import os
filename, extension = os.path.splitext(sys.argv[1])
with open(filename+extension, encoding='utf-8-sig') as (file
  ), open(filename+"_unwrapped"+extension, 'w', encoding='utf-8-sig') as (output
  ):
    *lines, last = list(file)
    for line in lines:
        if line == "n":
            line = "nn"
        elif line[0] == "t":
            line = "n" + line[:-1] + " "
        else:
            line = line[:-1] + " "
        output.write(line)
    output.write(last)
  • 只有换行符的"空白"行将变为两个换行符(以替换从上一行删除的换行符)。这将处理使用两个换行符分隔段落的文件
  • 以制表符开头的行将获得前导换行符(以替换从上一行删除的换行符),并将其尾部换行符替换为空格。这将处理使用制表符分隔段落的文件
  • 既不是空白也不是以制表符开头的行,其尾部换行符将替换为空格
  • 文件中的最后一行可能没有换行符,因此会直接复制

最新更新