如何使用awk就地更改文件?(与“ sed -i”一样)


11

我有一个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

Answers:


16

GNU awk(在Linux系统中常见的),由于4.1.0版本,能够以包括“ awk源库”与-i--include在命令行上。一个是分布与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在临时文件上运行,而不在原始文件上运行)可确保原始文件的文件元数据(权限和所有权)不会被修改。


4

尝试这个。

awk  new.awk sample.csv > tmp.csv && mv -f tmp.csv sample.csv
  • 将输出重定向到临时文件。
  • 然后将临时文件的内容移动到原始文件。

1
如果查看awk就地源代码,它就是这样做的:创建一个临时文件,在那里重定向stdout,最后将其重命名为输入文件。
chx
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.