【发布时间】:2021-04-23 06:57:33
【问题描述】:
我正在学习awk,我想知道是否有将更改写入文件的选项,类似于sed,我将使用-i 选项将修改保存到文件。
我明白我可以使用重定向来编写更改。但是awk 中是否有一个选项可以做到这一点?
【问题讨论】:
-
如果有人想用非 GNU
awk进行就地保存,也可以使用以下链接 stackoverflow.com/questions/59243104/… 供参考。
我正在学习awk,我想知道是否有将更改写入文件的选项,类似于sed,我将使用-i 选项将修改保存到文件。
我明白我可以使用重定向来编写更改。但是awk 中是否有一个选项可以做到这一点?
【问题讨论】:
awk 进行就地保存,也可以使用以下链接 stackoverflow.com/questions/59243104/… 供参考。
在 GNU Awk 4.1.0(2013 年发布)及更高版本中,它有 "inplace" file editing 的选项:
[...] 使用新工具构建的“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
【讨论】:
inplace 实际上是一个包含在gawk 中的库,所以inplace 是可以作为includefile 包含的东西。
除非您有 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
我很高兴添加了这个功能,但对我来说,实现并不是很尴尬,因为它的强大之处在于语言的简洁性,而且-i inplace 的 8 个字符太长了i.m.o。
这里是manual 的官方链接。
【讨论】:
awk '{ gsub(/foo/, "bar" ) } ; { print $0 }' file > tmp.txt && mv -v tmp.txt file 吗?
awk '{print $0}' file | sponge file 使用来自moreutils 的sponge。
只是一个有效的小技巧
echo "$(awk '{awk code}' file)" > file
【讨论】:
-i inplace 方法破坏了硬链接,这个 hack 遵循硬链接♥♥
这不行:
someprocess < file > file
shell 在将控制权移交给某个进程 (redirections) 之前 执行重定向。 > 重定向会将文件截断为零大小 (redirecting output)。因此,当某个进程启动并想要从文件中读取数据时,已经没有数据可供它读取了。
【讨论】:
另一种方法是使用sponge:
awk '{print $0}' your_file | sponge your_file
您将'{print $0}' 替换为您的awk 脚本,将your_file 替换为您要就地编辑的文件的名称。
sponge 在将输入保存到文件之前将其完全吸收。
【讨论】:
sponge 是moreutils 的一部分。所以它不会在大多数系统中默认出现。但看起来至少sponge 本身足够便携,几乎可以在任何地方运行。
tee 的解决方案相比,该解决方案的缺点是sponge 将在写入之前将所有内容读取到RAM,因此它会冻结大文件。
以下操作无效
echo $(awk '{awk code}' file) > file
这应该可以工作
echo "$(awk '{awk code}' file)" > file
【讨论】:
如果您想要一个仅 awk 的解决方案而不创建临时文件并且可以与 version!=(gawk 4.1.0) 一起使用:
awk '{a[b++]=$0} END {for(c=0;c<=b;c++)print a[c]>ARGV[1]}' file
【讨论】: