Bluepostech

まじめなことを書きます

【awk】タイトル行を飛ばしてデータファイルを処理する

awkというスクリプト言語がある。テキストファイルを行ごとに処理することが目的の言語で、perlpythonの元になった言語の1つだ。Linux上では実験やシュミレーションデータはテキストファイルで出てきて、それをgnuplotなどでプロットしていくことになるので、awkを使いこなせれば非常に強いツールになる。

最大値や平均値のようなデータを取り出すことはとても簡単で、コマンドラインに直接処理内容を打ち込むワンライナーで実行できる。

gawk 'max>$2{max=$2}END{print max}' sample.txt

awkがわかってる人でないとわかりにくいので、スクリプトファイルに書き出すと、次のようになる。

max<$2{
max=$2
}
END{
print max
}

これを書いてファイルに保存(ここではmax.awkとする)し、次のコマンドで実行しても同じことになる。

gawk -f max.awk sample.txt

テキストの処理は1行ずつ行われる。まず、$2は区切り文字で区切られた2列目のデータを意味する。

やっていることとしては単純で、最初のカッコは「変数maxが2行目の数より小さければ、maxを2行目の数に更新する」という動作を意味する。END以下はすべての行を処理し終わった後に実行されるコマンドで、maxを表示するということを意味する。つまり最大値の候補より大きい数が見つかればその数を最大値として更新して、最後に表示するというスクリプトだ。

完全に数値のみのファイルを処理するならこれで問題ないのだが、1行目にタイトルがついているファイルを処理すると、タイトルの文字が表示されるという不具合が出る。おそらく仕組みはこうだ。まず最初にタイトル行がmaxに文字列として格納される。次に数値と比較するが、文字列はそもそも大小の比較ができないので条件が真になることがない。そして最後にmaxに格納された文字列が表示される。

これを防ぐにはタイトル行は処理しないということが必要になる。したがって条件の部分に2行目以降だけ処理するという条件を足せばよい。awkではNRという変数で行数を表す。論理積は&&で表現できる。

なのでそれを考慮すると、次のようにすればよい。

gawk 'NR>1&&max>$2{max=$2}END{print max}' sample.txt

これでタイトル行を無視することができる。