awkで処理結果を元になったファイルに上書きする

ふと、「awkでファイルの上書き保存ってどうすんだろうなぁ…。GNU sedだったら-iオプションで上書きできるけど、awkだとんなオプションなかったよなぁ…」と思ってちょっと調べてみたところ、どうやらGNU awkの場合だと4.1.0以降で上書きができるようになってたらしい。 知らなかった…。 以下のように、-i inplaceで指定することで上書きができるようだ(参考:The GNU Awk User’s Guide: Extension Sample Inplace)。

awk -i inplace '{ ... }' File.path

blacknon@BS-PUB-DEVELOP:~$ awk --version | head -1
GNU Awk 4.1.3, API: 1.1 (GNU MPFR 3.1.4, GNU MP 6.1.0)
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt
A_01 A_02 A_03 A_04 A_05
B_01 B_02 B_03 B_04 B_05
C_01 C_02 C_03 C_04 C_05
D_01 D_02 D_03 D_04 D_05
E_01 E_02 E_03 E_04 E_05
F_01 F_02 F_03 F_04 F_05
G_01 G_02 G_03 G_04 G_05
H_01 H_02 H_03 H_04 H_05
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ awk 'NR>4{print $1}' awk_test.txt
E_01
F_01
G_01
H_01
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ awk -i inplace 'NR>4{print $1}' awk_test.txt
blacknon@BS-PUB-DEVELOP:~$
blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt
E_01
F_01
G_01
H_01

2017/06/11 追記

なお、このとき「INPLACE_SUFFIX」にバックアップファイルのサフィックスを設定することで、バックアップファイルを作成してくれるようになる。

blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt
A_01 A_02 A_03 A_04 A_05
B_01 B_02 B_03 B_04 B_05
C_01 C_02 C_03 C_04 C_05
D_01 D_02 D_03 D_04 D_05
E_01 E_02 E_03 E_04 E_05
F_01 F_02 F_03 F_04 F_05
G_01 G_02 G_03 G_04 G_05
H_01 H_02 H_03 H_04 H_05
blacknon@BS-PUB-DEVELOP:~$ awk -i inplace -v INPLACE_SUFFIX=.$(date +%Y%m%d_%H%M%S).bak 'NR>4{print $1}' awk_test.txt
blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt
E_01
F_01
G_01
H_01
blacknon@BS-PUB-DEVELOP:~$ cat awk_test.txt.20170611_212843.bak
A_01 A_02 A_03 A_04 A_05
B_01 B_02 B_03 B_04 B_05
C_01 C_02 C_03 C_04 C_05
D_01 D_02 D_03 D_04 D_05
E_01 E_02 E_03 E_04 E_05
F_01 F_02 F_03 F_04 F_05
G_01 G_02 G_03 G_04 G_05
H_01 H_02 H_03 H_04 H_05

知らなかった…。こんな便利な機能があったとは…。 ただ、残念ながらCentOS 7などでは、デフォルトで用意されているawkのバージョンがちょっと古く(手元の環境だと4.0.2とか)、この機能は使えなそう。 とりあえず、サブシェルでうまいことやれば上書き自体はできるけど…。 正直、毎回書きたくないなぁ…。

awk '{ ... }' file.path > >(sleep 1 && cat > file.path)
[root@BS-PUB-CENT7-01 ~]# cat test.txt
a01 a02 a03 a04 a05 a06 a07 a08 a09 a10
b01 b02 b03 b04 b05 b06 b07 b08 b09 b10
[root@BS-PUB-CENT7-01 ~]# awk '{print $1}' test.txt
a01
b01
[root@BS-PUB-CENT7-01 ~]# awk '{print $1}' test.txt > >(sleep 1 && cat > test.txt)
[root@BS-PUB-CENT7-01 ~]# cat test.txt
<span style="color: #ff0000;">a01
b01</span>
[root@BS-PUB-CENT7-01 ~]# awk --version | head -1
GNU Awk 4.0.2