使用Python编辑文本文件

6 投票
6 回答
38842 浏览
提问于 2025-04-15 15:08

我需要在我的IP地址变化时更新一个文本文件,然后再从命令行运行几个命令。

  1. 首先,创建一个变量 LASTKNOWN = "212.171.135.53"。这个是我们在写这个脚本时的IP地址。

  2. 获取当前的IP地址。这个地址每天都会变化。

  3. 为新的IP地址创建一个变量 CURRENT。

  4. 将 CURRENT 和 LASTKNOWN 进行比较(当作字符串比较)。

  5. 如果它们是一样的,就退出程序。

  6. 如果它们不一样,

    A. 将包含 LASTKNOWN IP 地址的旧配置文件 (/etc/ipf.conf) 复制到 /tmp 文件夹。
    B. 在 /tmp/ipf.conf 文件中将 LASTKNOWN 替换为 CURRENT。
    C. 使用子进程命令 "mv /tmp/ipf.conf /etc/ipf.conf" 来移动文件。
    D. 使用子进程命令执行 "ipf -Fa -f /etc/ipf.conf"。
    E. 使用子进程命令执行 "ipnat -CF -f /etc/ipnat.conf"。

  7. 最后,退出程序。

我知道如何完成步骤1到6,但在“文件编辑”部分(A到C)遇到了困难。我不知道该用哪个模块,或者是否应该直接在文件中编辑。方法有很多,我无法决定哪种方式最好。我想要一种比较保守的方法。

我知道如何使用子进程,所以你不需要对此进行评论。

我不想替换整行,只想替换特定的IP地址。

谢谢!

6 个回答

8

把 /etc/ipf.conf 文件中的 LASTKNOWN 替换成 CURRENT

一次性替换所有

filename = "/etc/ipf.conf"
text = open(filename).read()
open(filename, "w").write(text.replace(LASTKNOWN, CURRENT))

逐行替换

from __future__ import with_statement
from contextlib import nested

in_filename, outfilename = "/etc/ipf.conf", "/tmp/ipf.conf"
with nested(open(in_filename), open(outfilename, "w")) as in_, out:
     for line in in_:
         out.write(line.replace(LASTKNOWN, CURRENT))
os.rename(outfilename, in_filename)

注意:"/tmp/ipf.conf" 应该用 tempfile.NamedTemporaryFile() 或类似的东西替代
注意:这个代码没有经过测试。

27

另一种简单地在原地编辑文件的方法是使用 fileinput 模块:

import fileinput, sys
for line in fileinput.input(["test.txt"], inplace=True):
    line = line.replace("car", "truck")
    # sys.stdout is redirected to the file
    sys.stdout.write(line)
4

fileinput模块的接口设计得很糟糕,我找到一个更好用的模块来完成这个任务 - in_place,下面是Python 3的一个例子:

import in_place

with in_place.InPlace('data.txt') as file:
    for line in file:
        line = line.replace('test', 'testZ')
        file.write(line)

这个模块和fileinput的主要区别在于:

  • 它不是通过劫持sys.stdout来工作的,而是返回一个新的文件句柄供你写入。
  • 这个文件句柄支持所有标准的输入输出方法,而不仅仅是readline()。

举个例子,fileinput只能逐行编辑,而in_place可以把整个文件读到内存中(如果文件不大),然后进行修改。

撰写回答