我查看过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 /有效方式来编写这段代码,我也会欢迎我自己学习的建议。
感谢您的帮助!
答案 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')
为了简单起见,我倾向于从stdin
和stdout
输入并输出到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
)