3

我环顾 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

4 回答 4

8

您可以做的另一件事是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的答案也是有效的,除了你说它是一个大文件。此方法可让您在 1 GB 的 RAM 上处理 TB 大小的文件。

于 2013-08-09T03:07:02.473 回答
7

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

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语句,以便自动关闭文件。

于 2013-08-09T02:55:20.423 回答
1

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

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

为了简单起见,我倾向于输入和stdin输出stdout。但这是品味(和规格)的问题。

from sys import stdin, stdout

忽略关于删除最后EOL[1] 的具体要求,只解决你自己的学习问题,整个事情可以这样写:

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

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

于 2013-08-09T05:09:04.110 回答
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()

瞧,开头或结尾没有额外的换行符。结果列表可能无法很好地扩展。(就像我遗漏了一样else

于 2013-08-09T03:00:00.667 回答