在Python中从用户输入逐行交互式编辑文件

-1 投票
2 回答
786 浏览
提问于 2025-04-18 16:34

我想知道如何在Python中逐行编辑一个文件。

比如说,我有一个文本文件,里面通常是这样的:

key value
key value
key value
key value
key value
...

每一行的内容不一定是相同的配对。这只是我解释的方式。

我想在终端上逐行显示键和值,然后我想做以下两件事之一:

- 只需按回车键(或者其他快捷键)继续读取(显示)下一行。

- 输入一个新值,然后按回车。这实际上会替换文件中显示的值,最后继续显示下一对键值。

一直到文件结束,或者直到我输入'quit'或其他关键词也可以,没关系。

- 能够返回到上一行会是个加分项(以防不小心跳到下一行),但现在不是特别重要。

我发现自己经常以一种非常乏味和重复的方式编辑大型文件,文本编辑器在按箭头键时光标到处乱跑,真的很让人沮丧。而且使用退格键删除也很烦人。

我知道如何在Python中读取文件和写入文件,但不知道如何以这种互动的方式来做。我只知道如何一次性写入整个文件。此外,我也不知道同时以读取和写入的方式打开同一个文件是否安全。我知道如何处理每一行,如何将文本拆分成值的列表等等……我真正需要的是理解如何在当前这一行修改文件,并且妥善处理这种交互。

那么,最好的方法是什么呢?

2 个回答

1

我会这样做:先把文本文件里的所有行都加载到一个列表里,然后逐行查看这个列表,边看边修改里面的内容。最后,当你到达最后一行或者想要的时候,就把这个完整的列表写回到同样名字的文件里,这样就会覆盖掉旧的文件。

1

所有的回答都集中在把文件内容加载到内存中,修改后再保存到磁盘上,所以我想试试另一种方法:

import os

sep = " "

with open("inline-t.txt", "rb+") as fd:
    seekpos = fd.tell()
    line = fd.readline()
    while line:
        print line
        next = raw_input(">>> ")
        if next == ":q":
            break
        if next:
            values = line.split(sep)
            newval = values[0] + sep + next + '\n'
            if len(newval) == len(line):
                fd.seek(seekpos)
                fd.write(newval)
                fd.flush()
                os.fsync(fd)
            else:
                remaining = fd.read()
                fd.seek(seekpos)
                fd.write(newval + remaining)
                fd.flush()
                os.fsync(fd)
                fd.seek(seekpos)
                line = fd.readline()
        seekpos = fd.tell()
        line = fd.readline()

这个脚本简单地打开文件,一行一行地读取,如果用户输入了新值,就会重写这一行。如果新数据的长度和原来的数据一样,那么只需要找到原来的位置写入就可以了。如果新数据的大小不一样,我们就需要清理一下。这样的话,就要把文件剩下的内容读取出来,和新数据拼接在一起,然后全部重新写回磁盘。使用fd.flush和os.fsync(fd)可以确保更改在写入后立刻在文件中生效。这可能不是性能最好的解决方案,但我觉得这更接近他所要求的。

另外,考虑到这段代码可能有一些小问题,我相信还有优化的空间——比如可以在开始时进行一次全局读取,以避免频繁读取整个文件,特别是当需要调整的更改比较多的时候,或者类似的做法。

撰写回答