![如何使用 awk 就地更改文件? (与“sed -i”一样)](https://linux22.com/image/146820/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%20awk%20%E5%B0%B1%E5%9C%B0%E6%9B%B4%E6%94%B9%E6%96%87%E4%BB%B6%EF%BC%9F%20%EF%BC%88%E4%B8%8E%E2%80%9Csed%20-i%E2%80%9D%E4%B8%80%E6%A0%B7%EF%BC%89.png)
我有一个awk
脚本new.awk
:
BEGIN { FS = OFS = "," }
NR == 1 {
for (i = 1; i <= NF; i++)
f[$i] = i
}
NR > 1 {
begSecs = mktime(gensub(/[":-]/, " ", "g", $(f["DateTime"])))
endSecs = begSecs + $(f["TotalDuration"])
$(f["CallEndTime"]) = strftime("%Y-%m-%d %H:%M:%S", endSecs)
}
{ print }
我在 shell 中调用这个
awk new.awk sample.csv
...但我可以看到终端中的变化。如何在文件中就地进行更改,就像使用时一样sed -i
?
答案1
GNU awk
(常见于 Linux 系统)从 4.1.0 版开始,可以在命令行中包含一个“源库”(请awk
参阅-i
--include
如何安全地使用 gawk 的 -i 选项或 @include 指令?以及下面 Stéphane 对与此相关的安全问题的评论)。随 GNU 分发的源库之一awk
是inplace
:
$ cat file
hello
there
$ awk -i inplace '/hello/ { print "oh,", $0 }' file
$ cat file
oh, hello
正如您所看到的,这使得代码的输出awk
替换了输入文件。there
由于程序不输出该行,因此不会保留该行。
对于awk
文件中的脚本,您可以像这样使用它
awk -i inplace -f script.awk datafile
如果该awk
变量INPLACE_SUFFIX
设置为字符串,则库将以原始文件作为文件名后缀进行备份。
awk -i inplace -v INPLACE_SUFFIX=.bak -f script.awk datafile
如果您有多个输入文件,则每个文件都可以单独就地编辑。但是您可以通过inplace=0
在该文件之前的命令行上使用来关闭文件(或一组文件)的就地编辑:
awk -i inplace -f script.awk file1 file2 inplace=0 file3 inplace=1 file4
在上面的命令中,file3
不会就地编辑。
要对单个文件进行更便携的“就地编辑”,请使用
tmpfile=$(mktemp)
cp file "$tmpfile" &&
awk '...some program here...' "$tmpfile" >file
rm "$tmpfile"
这会将输入文件复制到临时位置,然后awk
在临时文件上应用代码,同时重定向到原始文件名。
按此顺序执行操作(awk
在临时文件上运行,而不是在原始文件上运行)可确保原始文件的文件元数据(权限和所有权)不会被修改。
答案2
尝试这个。
awk new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
- 将输出重定向到临时文件。
- 然后将临时文件的内容移动到原始文件。