今回はファイル処理をワンラインで行う強力な味方、awkコマンドをご紹介。本稿ではawkコマンドの基本的な使い方を解説します。
目次
・awkコマンドの用法
・awkコマンドを使ってみよう
特定の列のデータだけ抜き出す
データの区切り文字をカンマにする
特定の文字で始まる(含む)行を抜き出す
・awkコマンドによる条件付き出力
数値比較によって絞り込んで出力する
・awkコマンドによる簡易数値計算
列データの最大・最小値を求める
列データの合計・平均を求める
整数・実数の桁合わせ(printf関数)
・組み込み関数
awkコマンドの用法
awkコマンドの基本的な使い方は以下のようになります。
$ awk 'パターン {アクション}' ファイル名
(※「$ 」はコマンド受付中のマークです。既に表示されているので皆さんが入力する必要はありません)
パターンというのは何らかの条件と考えておけばOKです。アクションはawkコマンドで行う何らかの操作を指します。awkコマンドは、特定のパターンに合致した行もしくはカラムの要素に対して指定したアクションを実行するコマンドと言えます。
※AWK(オーク)は元々プログラミング言語の一つであり、UnixやLinux環境でファイル操作を簡単に行えるように開発されたものです。ワンラインで色々やるならPerlでもできます。
awkコマンドを使ってみよう
例えば、以下のように「dataset.txt」というファイルにa、b、cの3系列のデータがリストとして書き込まれているとします。
» データセット
1 0.182218988 a 3 0.297784751 a 7 0.360555096 a 8 0.372087519 a 9 0.409256577 a 15 0.565621684 a 17 0.613346197 a 21 0.678362497 a 23 0.714005697 a 26 0.807226012 a 31 0.842764672 a 32 0.847292094 a 36 0.881504968 a 40 0.973405431 a 43 0.987763106 a 46 1.014998976 a 48 1.02223779 a 53 1.094431056 a 54 1.107053052 a 57 1.162548999 a 59 1.22366798 a 61 1.286940823 a 62 1.305921405 a 66 1.440008501 a 68 1.536580082 a 2 0.230268945 b 4 0.306062235 b 5 0.310469045 b 6 0.339786199 b 10 0.469558639 b 12 0.534505967 b 14 0.563187878 b 18 0.616513133 b 19 0.648537306 b 28 0.827033352 b 30 0.838900174 b 34 0.871590963 b 35 0.877929505 b 37 0.900402407 b 44 0.992150485 b 47 1.020659782 b 50 1.074472053 b 56 1.126128635 b 58 1.191423735 b 60 1.230548034 b 63 1.327300318 b 64 1.348933769 b 67 1.456096108 b 11 0.522872415 c 13 0.536040293 c 16 0.597841941 c 20 0.67797903 c 22 0.694680553 c 24 0.773443168 c 25 0.777163356 c 27 0.815538433 c 29 0.82740152 c 33 0.85021772 c 38 0.958370643 c 39 0.962444199 c 41 0.983144472 c 42 0.985217274 c 45 1.014833774 c 49 1.035404769 c 51 1.081017564 c 52 1.087560751 c 55 1.12527036 c 65 1.350717734 c
» 閉じる
例えば、
$ cat dataset.txt | awk '{print}'
とすると全ての行を出力します。これは「awk ‘{print $0}’」としても同じ結果になります。
※「|」は「パイプ」、もしくは「パイプライン」と呼ばれるコマンドの入出力を繋ぐもので、これにより “cat dataset.txt” の出力結果に対して “awk ‘{print}'” という別のコマンドを適用することができます。
3列のデータのうち2列目だけを表示したいときは
$ cat dataset.txt | awk '{print $2}'
とします。
また、系列cのデータだけ抜き出したいときは
$ cat dataset.txt | awk '$3=="c" {print $2}'
とします。awkコマンドの「$3==”c”」という部分が「パターン」に相当します。これは「3カラム目の値($3)が “c” のとき2カラム目の値($2)を表示する」という意味です。
データの出力は複数個指定できて、「awk ‘{print $2 , $3}’」のようにすると2カラム目の値と3カラム目の値が空白で区切られて出力されます。
データの区切り文字をカンマにしたいときは例えば
$ cat dataset.txt | awk '{print $2 ", " $3}'
のようにします。
また、例えば
$ cat dataset.txt | awk '$3=="c" {print}'
↓
11 0.522872415 c 13 0.536040293 c 16 0.597841941 c 20 0.67797903 c 22 0.694680553 c 24 0.773443168 c 25 0.777163356 c 27 0.815538433 c 29 0.82740152 c 33 0.85021772 c 38 0.958370643 c 39 0.962444199 c 41 0.983144472 c 42 0.985217274 c 45 1.014833774 c 49 1.035404769 c 51 1.081017564 c 52 1.087560751 c 55 1.12527036 c 65 1.350717734 c
のように、該当する行を抜き出すこともできます(grepコマンドのように使える)。
awkコマンドではcutコマンドのように区切り文字(delimiter)を指定しなくても良いという強みがあります(指定したい場合は-Fオプションを使う)。また、条件を色々と指定できるのでgrepコマンドより細かい運用も可能なところが魅力です。今までcutコマンドやgrepコマンド、sedコマンドを駆使してデータの整理をしていたのが、awkコマンドではラクラクということも有り得ます。
awkコマンドによる条件付き出力
awkコマンドでは、ある要素に対して数値比較をして絞り込んだ上で出力することが可能です。
例えば、2列目の数値が1より大きい要素を取り出したいときは
$ cat dataset.txt | awk '$2 > 1 {print}'
のようにします。パターンのところに “$2 > 1” と書くことで、2列目の数値と1との大小を比較することができます。
さらに、and条件やor条件も指定可能です。
$ cat dataset.txt | awk '0.5 < $2 && $2 < 1 {print}'
この場合は2列目の数値が 0.5~1 の範囲(0.5 より大きい、かつ 1 未満)にある行がすべて抜き出されます。
2列目の数値が 0.5 未満、もしくは 1 以上である行を抜き出すときは
$ cat dataset.txt | awk '0.5 > $2 || $2 >= 1 {print}'
とします。
このようなタイプの行(または要素)の抽出をgrepコマンドで行うのは難しいですよね。awkコマンドはこうした数値を判別・評価して抜き出したりする操作が得意です。
awkコマンドによる簡易数値計算
awkコマンドを用いることで、各データに対して数値計算を行うことが可能です。
●最大値を求める
2列目のデータの最大値を抜き出します。
$ awk 'NR==1 {max=$2} {if($2 > max) max = $2} END {print max}' dataset.txt
↓
1.536580082
●最小値を求める
2列目のデータの最小値を抜き出します。
$ awk 'NR==1 {min=$2} {if($2 < max) min = $2} END {print min}' dataset.txt
↓
0.182218988
●合計を求める
2列目のデータの総和を計算します。
$ awk '{sum+=$2} END {print sum}' dataset.txt
↓
58.4872
●平均を求める
2列目のデータの平均を計算します。
$ awk '{sum+=$2}END{print sum/NR}' dataset.txt
↓
0.847641
“sum/NR” で変数sumの値を要素数で割ることができます。
●整数・実数の桁合わせ(printf関数)
上記の合計を求めるコマンドでは小数点以下4桁までしか出力されていませんが、printf関数を使えば整数でも小数でもC言語のように桁合わせ可能です。例えば以下のように指定することができます。
$ awk '{sum+=$2} END {printf "%2.8f\n", sum}' dataset.txt
↓
58.48720259
同様に平均の計算でもprintf関数を使えば桁数を調整できます。
printf関数で指定できる書式は以下の通りです。
メタ文字 | 説明 |
---|---|
%c | ASCIIの1文字 |
%d | 整数 |
%nd | n桁の整数 |
%0nd | n桁の整数(桁数がnに満たない場合は0で埋める) |
%f | 浮動小数点 |
%x.yf | 整数部分x桁、小数部分y桁の浮動小数点 |
%e | 指数形式 |
%o | 符号なし8進数 |
%s | 文字列 |
%ns | n文字までの文字列 |
%% | 「%」(”%%”と書くことでエスケープされる) |
組み込み関数
awkには次のような組み込み関数が用意されています。これによりデータ処理の幅が広がります。
関数 | 説明 |
---|---|
cos | 余弦(コサイン)を返す |
exp | 指数を返す |
getline | 次のレコードを読み込む |
index | 指定した文字列が最初に出現する位置を返す |
int | 小数点以下を切り捨てた整数を返す |
length | 文字列の長さ(文字数)を返す |
log | 自然対数を返す |
match | 指定した正規表現が最初に出現する位置を返す |
sin | 正弦(サイン)を返す |
split | 文字列を配列要素に分解して要素数を返す |
sprintf | 書式に従って文字列に変換する |
sqrt | 平方根を返す |
substr | 部分文字列を返す |
今回はawkコマンドの基本的な使い方についてまとめました。大規模にデータを整理するシェルスクリプトを書く際に重宝するコマンドの一つで、使い方次第ではもっと色々なことができるので、どんどん使いこなしていきましょう!