awkを使ってファイルを変更する方法は? ("sed -i"と同じ)

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 }

私はこれをシェルから呼びます。

awk new.awk sample.csv

...しかし、端末で変更を見ることができます。を使用するときと同じように、ファイルの内容をどのように変更できますかsed -i

ベストアンサー1

GNU awk(Linuxシステムで共通)バージョン4.1.0以降、コマンドラインに「ソースライブラリ」を含めることができますawk-i--includegawkの-iオプションまたは@includeディレクティブを安全に使用する方法は?そして、これに関連するセキュリティ問題に関する以下のStéphaneのコメント)。 GNUと共に配布されるソースライブラリの1つ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元のファイルではなく一時ファイルで実行)、元のファイルのファイルメタデータ(権限と所有権)は変更されません。

おすすめ記事