エンタープライズIT系エンジニアのぼやっきー

特にまとまりもなく、色々なことをぼやきます。最近はオープンソースの業務系システムに興味あり。

AWKがすごいのでメモ

awkが結構すごいので一応記事にしておきます。(よく忘れるし)

カテゴリ集計

CSVフォーマットを以下と仮定します。

日付(yyyy-MM-dd HH:mm:ss), 種別, サブ種別, 数値

とした時に、日毎に種別毎のサブ種別の合計値を求めます。

cat hoge.csv | awk 'BEGIN {FS=",";OFS=","}{\
sum[substr($1,0,10),$2,$3]+=$4}END{\
for (key in sum) {num=split(key, arr, "\034"); print arr[1],arr[2],arr[3], sum[key]}}'\
> summary.csv

日毎なので、yyyy-MM-dd以外の部分を配列キーに含めないようにします。
多次元配列のキーは\034で結合され、1次元配列と同じように1つの文字列で取り扱うことになります。
そのため、出力時は\034でsplitした配列から取り出せば元々指定したキーが個別に取り出せます。

なお、ENDを抜かすと都度出力になってしまうので集計されません。
(実はEND書き忘れてハマった。。)

distinct的な重複レコードの排除

cat hoge.csv | awk 'BEGIN {FS=",";OFS=","}!colname[$3]++{print $3,$4,$5}' > hogehoge.csv

例の場合は3列目をキーにして、3,4,5列目を出力します。
3列目が同じ値が出てきた場合は出力されません。(重複排除)

ENDがないのがポイントで、都度判定をして出力しています。
また、colname[$3]++でインクリメントしているため、初回出現時にprintが呼ばれ、その後に1が入ります。
次回出現時は1が入っているので「!」によって否定され、printが実行されません。

ネタです。

CSVをそのままDBに流せば良いのですが、awkで遊ぶためにinsert文に変えてみました。

cat hoge.csv | awk 'BEGIN {FS=",";OFS=" "}{ print \
"insert into hoge(id,  str, num,)\
values($1",\047"$2"\047,"$3");"}'\
> hoge.sql

シングルコーテーションは\047で指定する必要があります。