Awkワンライナー (最小値、最大値、合計、平均、中央値)

簡単な解析はワンライナーでやっちゃおう。ということでまずは簡単に最小値と最大値と平均を求めるAwkワンライナーを書きます。

たとえば以下のようなログファイルがあるとする。僕はいま、3列目の数値に対して統計値を出したいのだ。

0 0 147.086
0 10 141.269
0 20 10000
0 30 2805.22
0 40 152.003
0 50 144.762
0 60 144.926

最大値

cat test.log | awk '{if(m<$3) m=$3} END{print m}'
{
  if(m<$3) m=$3
}
END {
  print m
}

$3ってのが第3番目の列という意味なので、ここを変えれば別のところも参照可能。BEGINの中で初期値を設定する必要があるのかなと思っていたけど、いきなりif(m>$3)を実際にやってみたら大丈夫だった。

最小値

基本的には同じ。不等号を変えただけ。

cat test.log | awk 'BEGIN{m=100000}{if(m>$3) m=$3} END{print m}'
{
  if(m>$3) m=$3
}
END {
  print m
}

最大値の場合は(空白よりも数値が大きいので)大丈夫だが、最小値の場合はダメ。最小値以上の初期値を設定する必要がある。

合計

cat test.log | awk '{m+=$3} END{print m;}'
{
  m+=$3
} 
END{
  print m;
}

平均

合計を応用してENDの中で適当にこねくり回せばいろんなことができる。

cat test.log | awk '{m+=$3} END{print m/NR;}'
{
  m+=$3
} 
END{
  print m/NR;
}

中央値

とても面倒だった。ワンライナーには向いてない気がする。正攻法があるのかな…。

cat test.log | awk '{print $3}' | sort | awk -v l=`a=(\`wc -l test.log\`); expr ${a[0]} / 2` 'NR==l{print $1}'

sortで並べ替えた後、wcコマンドで行数を取得して2で割り、awkのシェル変数を導入するオプション-vを使って真ん中の行の数値を書き出す、という流れ。exprコマンドが小数を扱えないので2で割ると切り捨てになるので、奇数行の時は中央から低い方に一つずれた値となる。

補足

ちなみに、空白行があったりコメント行があるとうまく動かない。
空白行は例えば平均の時は以下の方法で何とかなるみたい。NFを使う。

NF>0{
  m+=$3
}
END {
  print m/NR
}