如何在python中格式化txt文件,以便删除额外的段落行以及额外的空格?

时间:2014-10-10 19:30:08

标签: python

我试图格式化与此类似的文件:(random.txt)

        Hi,    im trying   to format  a new txt document so
that extra     spaces between    words   and paragraphs   are only 1.



   This should make     this txt document look like:

这应该如下所示:(randomoutput.txt)

Hi, I'm trying to format a new txt document so
that extra spaces between words and paragraphs are only 1.

This should make this txt document look like:

到目前为止,我设法制作的代码只删除了空格,但是我无法识别新段落的开头位置,因此它不会删除空白行之间的空行。段落。这是我到目前为止所做的。

def removespaces(input, output):
    ivar = open(input, 'r')
    ovar = open(output, 'w')
    n = ivar.read()
    ovar.write(' '.join(n.split()))
    ivar.close()
    ovar.close()

编辑:

我还找到了一种在段落之间创建空格的方法,但是现在它只需要每个换行符并使用以下内容在旧行和新行之间创建一个空格:

m = ivar.readlines()
m[:] = [i for i in m if i != '\n']
ovar.write('\n'.join(m))

6 个答案:

答案 0 :(得分:2)

您应该逐行处理输入。这不仅可以使您的程序更简单,而且还可以更容易地在系统内存中使用。

规范化一行中水平空白区域的逻辑保持不变(拆分单词并用单个空格连接)。

你需要为段落做的是测试line.strip()是否为空(只是将它用作布尔表达式)并保持一个标志,前一行是否也是空的。你只需丢弃空行,但如果遇到非空行并设置了标志,则在它之前打印一个空行。

with open('input.txt', 'r') as istr:
    new_par = False
    for line in istr:
        line = line.strip()
        if not line:  # blank
            new_par = True
            continue
        if new_par:
            print()  # print a single blank line
        print(' '.join(line.split()))
        new_par = False

如果要取消文件顶部的空行,则需要在遇到第一个非空白行后才设置的额外标记。

如果你想更加花哨,请看一下textwrap模块,但要注意它有(或者,至少,从我能说的话),有一些糟糕的最坏情况表现的问题。

答案 1 :(得分:1)

这里的诀窍是你要将2个或更多\n的任何序列转换为2 \n个字符。仅使用splitjoin很难写出来 - 但使用re.sub编写它很简单:

n = re.sub(r'\n\n+', r'\n\n', n)

如果你想要只有空格的行被视为空白行,那么在剥离空格后执行;如果您希望将它们视为非空白,请在之前执行

您可能还希望更改空间剥离代码以使用split(' ')而不仅仅是split(),因此它不会搞砸新行。 (您也可以使用re.sub,但这并不是必需的,因为将1个或更多空格转换为1 并不难以写入 splitjoin。)


或者,您可以逐行进行,并跟踪最后一行(在循环内部使用显式变量,或者通过编写一个简单的adjacent_pairs迭代器,如i1, i2 = tee(ivar); next(i2); return zip_longest(i1, i2, fillvalue=''))以及当前行并且前一行都是空白的,不要写当前行。

答案 2 :(得分:0)

如果有空格(空格,制表符,换行符......),

split without Argument会在每次出现时剪切你的字符串。 写     n.split("") 它只会在空格处分开。 而不是将输出写入文件,将其放入Ingo a New变量,并再次重复该步骤,这次使用

m.split("\n")

答案 3 :(得分:0)

首先,让我们看看,究竟是什么问题...... 您不能有1个以上的连续空格或2个以上的连续换行符。

您知道如何处理1个以上的空格。 这种方法不适用于2个换行符,因为有3种可能的情况:    - 1个换行符    - 2个换行符    - 2 +新行

太棒了..你怎么解决这个问题呢? 有很多解决方案。我将列出其中的3个。

  1. 基于正则表达式。 这个问题很容易解决iff 1 你知道如何使用正则表达式... 所以,这是代码:

    s = re.sub(r'\n{2,}', r'\n\n', in_file.read())
    

    如果您有内存限制,这不是我们将整个文件读入内容时的最佳方式。

  2. 基于循环。 这段代码实际上是自我解释的,但无论如何我写了这条线......

    s = in_file.read()
    while "\n\n\n" in s:
        s = s.replace("\n\n\n", "\n\n")
    

    同样,你有内存限制,我们仍然将整个文件读入内容。

  3. 以州为基础。 解决这个问题的另一种方法是逐行。通过跟踪我们遇到的最后一行是否为空白,我们可以决定做什么。

    was_last_line_blank = False
    for line in in_file:
        # Uncomment if you consider lines with only spaces blank
        # line = line.strip()
    
        if not line:
            was_last_line_blank = True
            continue
        if not was_last_line_blank:
            # Add a new line to output file
            out_file.write("\n")
        # Write contents of `line` in file
        out_file.write(line)
    
        was_last_line_blank = False
    
  4. 现在,其中2个需要你将整个文件加载到内存中,另一个则要复杂得多。我的观点是:所有这些都有效,但由于它们的工作存在细微差别,因此它们在系统上的需求各不相同......

    1 “iff”是故意的。

答案 4 :(得分:0)

基本上,你想要获取非空的行(所以line.strip()返回空字符串,这是布尔上下文中的False。您可以使用列表/生成器理解对str.splitlines()的结果执行此操作,并使用if子句过滤掉空行。

然后,对于您要确保的每一行,所有单词都由单个空格分隔 - 为此,您可以对' '.join()的结果使用str.split()

所以这应该为你做的工作:

compressed = '\n'.join(
    ' '.join(line.split()) for line in txt.splitlines() 
        if line.strip() 
    )

或者您可以将filtermap与帮助函数一起使用,以使其更具可读性:

def squash_line(line):
    return ' '.join(line.split())

non_empty_lines = filter(str.strip, txt.splitlines())
compressed = '\n'.join(map(squash_line, non_empty_lines))

答案 5 :(得分:-1)

修复段落问题:

import re
data = open("data.txt").read()

result = re.sub("[\n]+", "\n\n", data)
print(result)