前回までフィルタコマンドとして「sed」を取り上げてきた。今回はsedコマンドよりもプログラミング言語色が強いコマンド「awk」を取り上げようと思う。
プログラミング言語色が強いコマンド「awk」
awkコマンドは、標準入力または入力ファイルから得られるデータを行ごとに処理するコマンドだ。sedコマンドよりもプログラミング言語的な特徴が強い。しかし、基本的に左から右へ流れていくデータを加工するフィルタコマンドとしての側面を持っているので、なかなかユニークなポジションにあると言える。
awkでは、基本的に次のように処理を指定して実行する。
パターン { 処理... }
パターン { 処理... }
パターン { 処理... }
パターン { 処理... }
...
パターン { 処理... }
パターンのところには、例えば「1列目の値がAの場合」とか「1列目と2列目の値が同じ場合」といった内容を指定する。また、特別なパターンとして1行目の前に一致する「BEGIN」、最後の行の後に一致する「END」、全ての行に一致する「指定なし」というものが存在する。それらも含めると、こんな感じになる。
BEGIN { 処理... }
パターン { 処理... }
パターン { 処理... }
パターン { 処理... }
パターン { 処理... }
...
パターン { 処理... }
{ 処理... }
END { 処理... }
これだけだとよくわからないと思うので、とりあえずawkを利用した例を見ていただこう。まず、次のような空白区切りのデータファイルを用意する。
舞茸 158 3
豆腐 178 3
納豆 96 1
卵 236 1
鶏モモ 528 3 賞味期限3日後
味噌 645 1
1列目が商品名、2列目が単価(円)、3列目が個数、4列目が備考だ。このデータを加工して表にするとともに、消費税と合計値を算出する処理をawkコマンドを使って実行すると次のようになる。
% cat data.ssv | awk '
BEGIN { printf("\t\t本日のお買い物\n\n")
printf("\t商品\t単価\t個数\t備考\n")
print "\t-------------------------------------"
}
$2~/^[0-9]+$/ { sum += $2 * $3 }
{ printf("\t%s\t%4d\t%4d\t%s\n",$1,$2,$3,$4) }
END { print "\t-------------------------------------"
printf("\t<3000>小計\t\t%4d 円\n",sum)
printf("\t消費税\t\t%4d 円\n",sum*0.08)
printf("\t<3000>合計\t\t%4d 円\n",sum*1.08)
}
'
本日のお買い物
商品 単価 個数 備考
-------------------------------------
商品 0 0 備考
水菜 99 2
舞茸 158 3
豆腐 178 3
納豆 96 1
卵 236 1
鶏モモ 528 3 賞味期限3日後
味噌 645 1
-------------------------------------
小計 3767 円
消費税 301 円
合計 4068 円
%
最初はこれだけだと相変わらずawkコマンドの役割が意味不明かもしれないが、実際は結構「使える」コマンドで、特にデータの加工などに向いている。sedと異なり、制御構文といくつかの関数が用意されているので、もっと込み入ったプログラミング言語的な書き方をして使うこともできる。
例えば、サーバの管理者にとって、よくある業務の1つがログデータの監視だが、awkコマンドを使えば簡単にログデータを加工できる。また、集計処理的なこともできるので、使い方に慣れさえすれば、なかなか便利なコマンドなのだ。もし、先にPHPやJavaScriptといったプログラミング言語を学んでいたりすると、最初はawkコマンドの書式で混乱するかもしれないが、要は慣れの問題だと思う。
Windowsで発生するデータ処理や雑務的なことも、awkコマンドでこなせることが多い。何にせよ、最終的にMicrosoft Excelのデータとして出力しておけばよいみたいなケースは多いのだ。そのため、スペース区切りのデータとして出力し、awkコマンドで処理して、最後にExcelに貼り付けて業務終了……といったことができるわけである。
Windows 10からはネイティブにLinuxコマンドを利用する方法も提供が始まっており、こうした機能を使わないのはもったない。本連載でも、これからしばらくは、この強力なコマンドawkについて取り上げようと思う。