是否可以就地修改文件中的行?

Posted

技术标签:

【中文标题】是否可以就地修改文件中的行?【英文标题】:Is it possible to modify lines in a file in-place? 【发布时间】:2011-03-27 23:39:58 【问题描述】:

是否可以逐行解析文件,并在遍历这些行时就地编辑一行?

【问题讨论】:

在某些条件下是可能的。如果编辑处理的行所产生的行较短或与处理的行相同,则很容易做到。如果不是这种情况,它会变得更加困难,尽管如果经过编辑的行不是太多的话,这并非不可能。你问这个是因为你想处理一个大文件吗? >>> f = open('tmp', 'r+') >>> f.readline() '75.14\n' >>> f.readline() '100\n' > >> l = _ >>> f.seek(-l.len(), file.SEEK_CUR) >>> f.seek(-len(l), os.SEEK_CUR) >>> f.write('999\ n') >>> f.close() >>> 在此处查看示例 (***.com/questions/5286020/…) edit text file using Python 我们可以用 bash 做吗? 【参考方案1】:

是否可以逐行解析文件,并在遍历这些行时就地编辑一行?

可以像 stdlib 的 fileinput module 那样使用备份文件进行模拟。

这是一个示例脚本,它从命令行或stdin 给出的文件中删除不满足some_condition 的行:

#!/usr/bin/env python
# grep_some_condition.py
import fileinput

for line in fileinput.input(inplace=True, backup='.bak'):
    if some_condition(line):
        print line, # this goes to the current file

例子:

$ python grep_some_condition.py first_file.txt second_file.txt

在完成时first_file.txtsecond_file.txt 文件将只包含满足some_condition() 谓词的行。

【讨论】:

实际上不写入文件中间的方法也是明智的,因为它很容易使修改原子化(也就是说,如果文件最终不会处于部分修改状态,如果程序被中断)。 啊,fileinput有一个files参数,docs.python.org/3/library/fileinput.html【参考方案2】:

fileinput 模块的 API 非常丑陋,我为这项任务找到了漂亮的模块 - 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)

与文件输入的主要区别:

不是劫持sys.stdout,而是返回一个新的文件句柄进行写入。 文件句柄支持所有标准 I/O 方法,而不仅仅是readline()

重要提示

    如果您不使用 file.write() 行重写文件,此解决方案会删除文件中的每一行。 此外,如果进程中断,您会丢失文件中尚未重写的任何行。

【讨论】:

【参考方案3】:

没有。您无法安全地写入正在阅读的文件,因为您对文件所做的任何更改都可能覆盖您尚未阅读的内容。为了安全地执行此操作,您必须将文件读入缓冲区,根据需要更新任何行,然后重新写入文件。

如果您要逐字节替换文件中的内容(即,如果您要替换的文本与您要替换的新字符串的长度相同),那么您可以摆脱它,但是这是一个马蜂窝,所以我会省去你的麻烦,只需阅读完整的文件,替换内存中的内容(或通过临时文件),然后再写出来。

【讨论】:

【参考方案4】:

如果您只打算执行不改变文件被修改部分长度的本地化更改(例如将所有字符更改为小写),那么您实际上可以动态覆盖文件的旧内容。

为此,您可以通过file 对象的seek() 方法使用随机文件访问。

或者,您可以使用mmap 对象将整个文件视为可变字符串。请记住,mmap 对象可能会在 32 位 CPU 上施加 2-4 GB 范围内的最大文件大小限制,具体取决于您的操作系统及其配置。

【讨论】:

【参考方案5】:

您必须以字符为单位备份行的大小。假设您使用了readline,那么您可以获取该行的长度并使用:

file.seek(offset[, whence])

将whence设置为SEEK_CUR,将offset设置为-length

请参阅Python Docs 或查看seek 的联机帮助页。

【讨论】:

以上是关于是否可以就地修改文件中的行?的主要内容,如果未能解决你的问题,请参考以下文章

替换 .plist 文件中的行以修改 <string> - 可以吗?

使用 Gulp.js 和 globbing 模式就地修改文件(相同的目标)

使用 awk 保存修改

如何通过就地过滤来修改python集合?

sed 修改文件中的行

删除列表列表中的第一项 - 制作副本而不是就地修改