我试图根据条件打印第-4行.我有一个SFU.txt包含一些内容的文本文件.我的目标是:如果configuration一行中有一个单词,我想打印第-4行.例如,如果我的文件内容如下所示:
This is a random text document
We are talking about planets here
This is planet Mars
in solarsystem
sun is the star
this is 4th planet
configuration lifeform exists
bla bla bla
bla bla bla
Run Code Online (Sandbox Code Playgroud)
所以,一旦编译器到达该行configuration lifeform exists并且它看到configuration,我想打印该行This is planet earth
我的代码如下:
file = open("SFU.txt","r")
for line in file:
if "configuration" in line:
#want to print the -4th line-HOW?
Run Code Online (Sandbox Code Playgroud)
使用tee运行对整个迭代器inf。这在任何给定时间只在内存中存储五行:
from itertools import tee
with open("SFU.txt") as inf:
# set up iterators
cfg,res = tee(inf)
# advance cfg by four lines
for i in range(4):
next(cfg)
for c,r in zip(cfg, res):
if "configuration" in c:
print(r)
Run Code Online (Sandbox Code Playgroud)
并且,正如预期的那样,导致
This is planet Mars
Run Code Online (Sandbox Code Playgroud)
编辑:如果你想编辑-4th行,我建议
def edited(r):
# make your changes to r
return new_r
with open("SFU.txt") as inf, open("edited.txt", "w") as outf:
# set up iterators
cfg, res = tee(inf)
for i in range(4):
next(cfg)
# iterate through in tandem
for c, r in zip(cfg, res):
if "configuration" in c:
r = edited(r)
outf.write(r)
# reached end - write out remaining queued values
for r in res:
outf.write(r)
Run Code Online (Sandbox Code Playgroud)
有限大小deque是保留最后几行"环形缓冲区"的好方法:
import collections
lastfewlines = collections.deque((), 4)
with open('SFU.txt') as f:
for line in f:
if 'configuration' in line and len(lastfewlines) == 4:
print(lastfewlines[0])
lastfewlines.append(line.rstrip())
Run Code Online (Sandbox Code Playgroud)
然而,虽然这解决了问题中提出的问题,但它不适用于OP仅在评论中提到的"实际问题" - "编辑"该行,意味着,可能会改变输入文件"就地" .
唉,现代文件系统并没有让文件的"就地编辑"除了字节对字节覆盖-除非"编辑"线是完全一样的字节数为原来的,你不能只是简单地覆盖说原始线,并想象文件中的所有以下行将根据需要来回移动! - )
相反,一个人必须读取文件,改变它并重写它(最有效的方法通常是写一个新文件,然后将其重命名为旧文件名",就像你的操作系统和文件系统会让你一样原子",如果发生崩溃,以避免丢失数据).
该deque方法可以适应这一点 - 而不仅仅是有条件地打印lastfewlines[0],将输出文件的原始版本或修改版本写入输出文件(并在最后写入deque输出文件中剩下的内容).然后,至少在Unix系统和本地文件系统上,一个简单的os.rename将执行原子技巧(只要输出文件与输入文件在同一个安装的磁盘上).
然而,对于所有但非常大的文件,读取内存中的所有行(带f.readlines()),在行列表中执行更改(如果有的话),然后再次写出批次,则要简单得多.并且由于用户提到16,000行(长度未指定但假设每个平均行少于100个字节),这个小于2兆字节的小文件应该以最简单的方式处理 - 它比任何文件小几个数量级这将导致任何"太大而不适合记忆"的担忧! - )