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 }

私はこれをシェルで呼び出しています

awk new.awk sample.csv

...しかし、ターミナルの変化を見ることができます。使用する場合のように、ファイル内の変更をインプレースにする方法はsed -i

回答:


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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.