不要将最终的新行字符写入文件

时间:2013-08-09 02:50:16

标签: python

我查看过StackOverflow并找不到我的具体问题的答案,请原谅我,如果我错过了什么。

import re

target = open('output.txt', 'w')

for line in open('input.txt', 'r'):
    match = re.search(r'Stuff', line)
    if match:
        match_text = match.group()
        target.write(match_text + '\n')
    else:
        continue
target.close()

我正在解析的文件非常庞大,因此需要逐行处理。

这(当然)在文件末尾留下了一个额外的换行符。

我应该如何最好地更改此代码,以便在'if match'循环的最后一次迭代中,它不会在文件末尾添加额外的换行符。它应该在最后再次查看文件并删除最后一行(虽然看起来有点效率不高)?

我发现的现有StackOverflow问题包括从文件中删除所有新行。

如果有更多的pythonic /有效方式来编写这段代码,我也会欢迎我自己学习的建议。

感谢您的帮助!

4 个答案:

答案 0 :(得分:6)

next 行的开头写下每行的换行符。要避免在第一行的开头写入换行符,请使用初始化为空字符串的变量,然后在循环中设置为换行符。

import re

with open('input.txt') as source, open('output.txt', 'w') as target:

    newline = ''
    for line in source:
        match = re.search(r'Stuff', line)
        if match:
            target.write(newline + match.group())
            newline = '\n'

我还重新构建了一些代码(不需要else: continue,因为循环还要做什么?)并将其更改为使用with语句,以便文件自动关闭

答案 1 :(得分:4)

您可以做的另一件事是truncate文件。 .tell()为我们提供了文件中的当前字节数。然后我们减去一个,并在那里截断它以删除尾随换行符。

with open('a.txt', 'w') as f:
    f.write('abc\n')
    f.write('def\n')
    f.truncate(f.tell()-1)

在Linux和MacOS上,-1是正确的,但在Windows上,它必须是-2。一种更加Pythonic的方法,用于确定检查os.linesep

import os
remove_chars = len(os.linesep)

with open('a.txt', 'w') as f:
    f.write('abc\n')
    f.write('def\n')
    f.truncate(f.tell() - remove_chars)

kindal 的回答也是有效的,除了您说它是一个大文件。这种方法可以让你在一个GB的RAM上处理一个TB级文件。

答案 2 :(得分:1)

由于你一遍又一遍地执行相同的正则表达式,你可能想要事先编译它。

import re
prog = re.compile(r'Stuff')

为了简单起见,我倾向于从stdinstdout输入并输出到from sys import stdin, stdout EOL。但这是品味(和规格)的问题。

from itertools import imap
stdout.writelines(match.group() for match in imap(prog.match, stdin) if match)

忽略了删除最终{{1}} [1]的具体要求,并且只是解决了关于你自己学习的问题,整个事情可以写成:

{{1}}

[1]正如其他人评论的那样,这是一件坏事,当有人这样做时,这是非常烦人的。

答案 3 :(得分:0)

从您拥有的最短路径可能是将结果存储在列表中,然后使用换行符加入列表并将其写入文件。

import re

target = open('output.txt', 'w')
results = []

for line in open('input.txt', 'r'):
    match = re.search(r'Stuff', line)
    if match:
        results.append(match.group())
target.write("\n".join(results))
target.close()

Voilà,在开始或结束时没有额外的换行符。结果列表可能无法很好地扩展。 (和我一样,我遗漏了else