
我有一個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
- 將輸出重定向到暫存檔案。
- 然後將臨時文件的內容移到原始文件。