156

我正在学习awk,我想知道是否有将更改写入文件的选项,类似于sed我使用-i选项将修改保存到文件的位置。

我明白我可以使用重定向来编写更改。但是有没有awk办法做到这一点?

4

7 回答 7

171

在 GNU Awk 4.1.0(2013 年发布)及更高版本中,它具有“就地”文件编辑选项:

[...] 使用新工具构建的“inplace”扩展可用于模拟 GNU“ sed -i”功能。[...]

示例用法:

$ gawk -i inplace '{ gsub(/foo/, "bar") }; { print }' file1 file2 file3

要保留备份:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{ gsub(/foo/, "bar") }
> { print }' file1 file2 file3
于 2013-05-13T22:03:18.037 回答
162

除非您有 GNU awk 4.1.0 或更高版本...

您将没有像 sed 的-i选项这样的选项,因此请执行以下操作:

$ awk '{print $0}' file > tmp && mv tmp file

注意:这-i并不神奇,它还创建了一个临时文件sed,只是为您处理它。


从 GNU awk 4.1.0 开始...

GNU awk在 4.1.0 版(2013 年 10 月 5 日发布)中添加了此功能。-i它不像发布的说明中描述的那样直接提供选项:

新的 -i 选项(来自 xgawk)用于加载 awk 库文件。这与 -f 的不同之处在于第一个非选项参数被视为脚本。

您需要使用捆绑inplace.awk的包含文件来正确调用扩展,如下所示:

$ cat file
123 abc
456 def
789 hij

$ gawk -i inplace '{print $1}' file

$ cat file
123
456
789

该变量INPLACE_SUFFIX可用于指定备份文件的扩展名:

$ gawk -i inplace -v INPLACE_SUFFIX=.bak '{print $1}' file

$ cat file
123
456
789

$ cat file.bak
123 abc
456 def
789 hij

我很高兴添加了这个功能,但对我来说,实现并不是很尴尬,因为它的功能来自语言的简洁性,而且imo-i inplace 8 个字符太长。

这是官方单词手册的链接。

于 2013-05-13T19:32:00.430 回答
26

只是一个有效的小技巧

echo "$(awk '{awk code}' file)" > file
于 2015-10-07T15:01:53.037 回答
17

@sudo_O有正确的答案

这是行不通的:

someprocess < file > file

shell在将控制权交给某个进程(重定向)之前执行重定向。重定向会将文件截断为零大小(重定向输出)。因此,当某个进程启动并想要从文件中读取时,它已经没有数据可以读取了。>

于 2013-05-13T20:43:05.273 回答
17

另一种方法是使用sponge

awk '{print $0}' your_file | sponge your_file

'{print $0}'用 awk 脚本和your_file要编辑的文件名替换的位置。

sponge在将输入保存到文件之前完全吸收输入。

于 2017-09-08T15:22:57.080 回答
6

以下不起作用

echo $(awk '{awk code}' file) > file

这应该工作

echo "$(awk '{awk code}' file)" > file
于 2016-05-14T16:10:49.217 回答
4

如果您想要一个仅 awk 的解决方案而不创建临时文件并且可以与 version!=(gawk 4.1.0) 一起使用:

awk '{a[b++]=$0} END {for(c=0;c<=b;c++)print a[c]>ARGV[1]}' file
于 2015-08-20T22:53:03.453 回答