使用 awk 进行就地编辑时如何刷新输出?

How to flush output when using inplace editing with awk?

我想使用 awk 编辑一个大文件 inplace 的列。如果由于任何原因,过程 break/stops,我不想失去已经完成的工作。我尝试添加 fflush 但似乎它不适合 inplace.

为了模拟出想要的结果,这里有一个包含 3 列的测试文件。最后一列全为零。

paste -d '\t' <(seq 1 10) <(seq 11 20) | 
    awk 'BEGIN {FS="\t"; OFS=FS} {$(NF+1)=0; print}' > testfile

然后我想替换最后一列中的值。在这个简单的示例中,我只是将它们替换为第一列和第二列的总和。我正在添加一个系统睡眠,因此可能会在中间中止脚本以查看结果。

awk -i inplace 'BEGIN {FS="\t"; OFS=FS} ==0{=+; print; fflush(); system("sleep 1")}' testfile

如果您 运行 脚本并在它结束前中止它 (ctrl+z),测试文件不会改变。

是否可以达到预期的结果(脚本中断或停止时得到部分结果)?我应该怎么做?

"In-place"编辑不是真的。一个临时文件保存输出,并替换脚本末尾的输入。

实际 就地编辑会很慢:除非输出与输入的长度相同,否则文件大小需要更改,并且 awk 会在每次缓冲区刷新时重新写入整个文件(至少是当前行之后的所有内容)。请注意来自 the documentation 的警告:

If the program dies prematurely … a temporary file may be left behind.

您可以编写一些恢复代码的脚本,以便在中止后将该临时文件与您的输入合并。

或者,您可以将脚本调整为每 运行 仅修改一行(并简单地打印每一行后续行,未修改),然后重新 运行 直到没有任何更改制作。这将强制 awk 在每次更改时重新写入文件。它会很慢,但是没有任何快速的方法可以从文件中间删除数据。