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

mit*_*ttu 12 linux shell awk

我有一个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 }
Run Code Online (Sandbox Code Playgroud)

我在 shell 中调用它

awk new.awk sample.csv
Run Code Online (Sandbox Code Playgroud)

...但我可以看到终端中的变化。如何在文件中进行就地更改,例如使用时sed -i

Kus*_*nda 20

GNU awk(通常在 Linux 系统上找到),从 4.1.0 版开始,能够在命令行中或在命令行上包含“awk源库” 。与 GNU 一起分发的源库之一称为:-i--includeawkinplace

$ cat file
hello
there
Run Code Online (Sandbox Code Playgroud)
$ awk -i inplace '/hello/ { print "oh,", $0 }' file
$ cat file
oh, hello
Run Code Online (Sandbox Code Playgroud)

如您所见,这使得awk代码的输出替换了输入文件。该行there没有保留,因为它不是由程序输出的。

使用awk文件中的脚本,您可以像这样使用它

awk -i inplace -f script.awk datafile
Run Code Online (Sandbox Code Playgroud)

如果awk变量INPLACE_SUFFIX设置为字符串,则库将使用该文件作为文件名后缀备份原始文件。

awk -i inplace -v INPLACE_SUFFIX=.bak -f script.awk datafile
Run Code Online (Sandbox Code Playgroud)

如果您有多个输入文件,则每个文件都可以单独就地编辑。但是您可以通过inplace=0在该文件之前的命令行上使用来关闭文件(或一组文件)的就地编辑:

awk -i inplace -f script.awk file1 file2 inplace=0 file3 inplace=1 file4
Run Code Online (Sandbox Code Playgroud)

在上面的命令中,file3不会就地编辑。


要对单个文件进行更便携的“就地编辑”,请使用

tmpfile=$(mktemp)
cp file "$tmpfile" &&
awk '...some program here...' "$tmpfile" >file
rm "$tmpfile"
Run Code Online (Sandbox Code Playgroud)

这会将输入文件复制到一个临时位置,然后awk在重定向到原始文件名的同时在临时文件上应用代码。

按此顺序执行操作(awk在临时文件上运行,而不是在原始文件上运行)可确保原始文件的文件元数据(权限和所有权)不被修改。


Siv*_*iva 7

尝试这个。

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

  • 如果您查看 awk inplace [源代码](http://git.savannah.gnu.org/cgit/gawk.git/tree/extension/inplace.c),这正是它的作用:创建一个临时文件,将 stdout 重定向到那里,最后将其重命名为输入文件。 (5认同)