使用GNU工具进行真正的就地文件编辑

时间:2017-04-27 18:17:27

标签: performance awk sed io

我有一个非常大(多千兆字节)的文件,我想对它进行简单的操作:

  • 在文件末尾添加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上。

2 个答案:

答案 0 :(得分:4)

在多GB文件的开头添加5-10行将始终要求完全重写该文件的内容,除非您使用的是提供非标准系统调用的操作系统和文件系统。 (您可以通过写回您正在修改的文件中的某个点来避免需要多GB的临时空间,但是不能避免重写一切都超过编辑点。)

这是因为UNIX只允许以一种在其现有端或之后更改其总体大小的方式向文件添加新内容。您可以编辑就地文件的一部分 - 也就是说,您可以搜索1GB并写入1MB的新内容 - 但这会更改先前在其中的1MB内容地点;它不会更改文件的总大小。同样,您可以在您选择的位置截断并重写文件,但是超出截断点的所有内容都需要重写

上面提到的非标准操作的一个示例是FALLOC_FL_INSERT_RANGEFALLOC_FL_COLLAPSE_RANGE操作,使用非常新的Linux内核将允许将块插入或移除现有文件。这对你不太有帮助:

  • 只能插入精确的块(即4kb - 无论文件系统的格式是什么),而不是单个任意大小的文本行。
  • 仅支持XFS和ext4。

请参阅fallocate(2)的文档。

答案 1 :(得分:1)

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

split -l 1000 -a 4 -d bigfile bigfile_

因为你需要空间,因为不会删除bigfile

将标题插入第一行

sed -i '1iheader` bigfile_000

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

grep pattern bigfile_*

完成所有编辑后,只需cat支持其余部分

cat bigfile_* > edited_bigfile