【问题标题】:True in-place file editing using GNU tools使用 GNU 工具进行真正的就地文件编辑
【发布时间】:2017-04-27 18:17:26
【问题描述】:

我有一个非常大(数 GB)的文件,我想对其进行简单操作:

  • 在文件末尾添加 5-10 行。
  • 在文件开头添加 2-3 行。
  • 在开头删除几行,直到某个子字符串。具体来说,我需要遍历文件直到显示“删除我!\n”的行,然后删除文件中直到并包括该行的所有行。

我正在努力寻找一种可以进行就地编辑的工具,而无需创建一个基本上包含我的原始文件副本的临时文件(非常长的任务)。基本上,我想尽量减少对磁盘的 I/O 操作次数。

sed -i 和 awk -i 都做的很慢 (https://askubuntu.com/questions/20414/find-and-replace-text-within-a-file-using-commands),因此效率低下。有什么更好的方法?

我在 Debian 上。

【问题讨论】:

  • echo "blabla" >> bigfile 将行添加到末尾。从头开始删除并不容易。最简单的方法是使用临时文件,例如-ised '....' file >newfile && mv newfile file
  • 在开头删除几行,直到某个子字符串 - 你能详细说明一下吗?什么子串和多少行?
  • @RomanPerekhrest 添加了关于它的解释。
  • @AlexWeinstein,你所要求的在很大程度上是不可能的。标准 UNIX 系统调用——用于用户空间应用程序请求文件系统操作的接口——允许就地附加到文件的 end;允许在原始值和新值长度完全相同的情况下进行就地编辑;但不要让您在任何时候追加数据或删除数据(以改变文件总长度的方式),但以不需要重写整个文件其余部分的方式结束。
  • 顺便说一句,这是一类问题,通常通过具有删除标志等的索引、日志结构文件格式来解决。也就是说,使用数据库。

标签: performance awk sed io


【解决方案1】:

在多 GB 文件的开头添加 5-10 行总是需要完全重写该文件的内容,除非您使用的操作系统和文件系统提供非标准系统调用。 (您可以通过将您正在修改的文件中的某个点回写到缓冲区中来避免需要多个 GB 的临时空间,但是您无法避免需要重写所有超出编辑点的内容)。

这是因为 UNIX 只允许向文件添加新内容,其方式是在其现有结尾处或之后更改其整体大小。您可以就地编辑文件的一部分——也就是说,你可以在其中寻找 1GB 并写入 1MB 的新内容——但这会改变之前存在的 1MB 内容地点;它不会改变文件的总大小。同样,您可以在您选择的位置截断和重写文件,但是超过截断点的所有内容都需要重写


上面提到的非标准操作的一个例子是FALLOC_FL_INSERT_RANGEFALLOC_FL_COLLAPSE_RANGE 操作,非常 新的 Linux 内核将允许在现有文件中插入或删除块。这不太可能对您有帮助:

  • 只能插入精确的块(即 4kb - 无论您的文件系统采用何种格式),不能插入任意大小的单行文本。
  • 仅支持 XFS 和 ext4。

请参阅fallocate(2) 的文档。

【讨论】:

    【解决方案2】:

    这里是编辑大文件的建议(根据您的文件长度和要处理的部分数量更改行数和位数)

    split -l 1000 -a 4 -d bigfile bigfile_
    

    为此您需要空间,因为不会删除大文件

    插入标题作为第一行

    sed -i '1iheader` bigfile_000
    

    搜索特定模式,获取文件名并删除前面的部分。

    grep pattern bigfile_*
    

    等等

    完成所有编辑后,只需 cat 将剩余部分返回

    cat bigfile_* > edited_bigfile
    

    【讨论】:

    • 非常有趣的方向... 后续问题:有没有办法让“split”命令对文件内容不做I/O?也就是把文件原地分割?
    • 不,它有定位线。
    • @AlexWeinstein:如果你能找到一个仍然足够小的字节块大小而不影响你的字符串搜索,你可以使用-b <bytes>而不是-l <lines>,虽然我不确定如果/在 I/O 方面有多大帮助。
    • @karakfa:您能否在您的答案中添加解释,说明为什么这种方法有助于处理大文件?这对我来说并不明显,因为您首先有效地创建了整个原始文件的副本,尽管是以块的形式。
    • 这将有助于编辑各个部分,尤其是在迭代执行任务时。这消除了为每个本地编辑多次扫描文件。否则,就没有魔法......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多