awkには最大値を算出する関数は用意されていないので、自作する必要がありました。
フィールド(列)を指定した最大値算出は、データ処理にとても便利なので、使っていくとどんどん世界が広がります。
サンプルコード
まずはサンプルコードです。
in.txtの4フィールド目(4列目)の最大値を算出しています。
sample.awkを実行すると、最大値が算出されています。
$ cat in.txt
2015 1 1 -4
2015 1 2 89
2015 1 3 99
2015 1 1 -4
2016 1 2 89
2016 1 3 99
2017 1 1 -4
2017 1 2 89
2017 1 3 99
$ cat sample.awk
#!/bin/sh
cat in.txt | awk '
BEGIN{
count = 0
}
{
year = $1
month = $2
day = $3
val = $4
if(count == 0){
max = val #初期値を設定
print "初期値を設定 max=" max
count++
}
if(val > max){
max = val #最大値を更新
print "最大値を更新 max=" max
}
}
END{
print "最大値=" max
}
'
$ ./sample.awk
初期値を設定 max=-4
最大値を更新 max=89
最大値を更新 max=99
最大値=99
いくつかポイントを下記に解説してみます。
まずは初期値の設定を慎重にすることが大事
まずは初期値を変数maxに設定します。
初期値の設定方法は色々とあると思います。
今回採用した方法は、1行目を読み込んだら初期値として設定する方法です。
カウンターを設けて、カウンターが0の場合は、初期値として設定しました。
BEGINブロックでカウンターを0とし、
BEGIN{
count = 0
}
1行目の処理をした時(カウンターが0の時)に、下記のように初期値を設定しています。
if(count == 0){
max = val #初期値を設定
print "初期値を設定 max=" max
count++
}
NR変数は使用していません。
NR変数で1行目を判定するのもありだと思いますが、最大値を算出するレコード(行)の範囲を変更した場合(1行目を最大値の算出対象としなかった場合)には、初期値の設定がされなくなってしまいます。
1行ずつ読み込んで、最大値を更新していく
あとは、1行ずつ読み込んで、変数maxの値と取得したフィールド(列)の値を比較して、
変数maxより大きければ変数maxを更新する基本的な計算方法です。
if(val > max){
max = val #最大値を更新
print "最大値を更新 max=" max
}
最大値の更新が終了したら、ENDブロックで最大値を出力
全ての行の読み込んが終了して最大値の更新が終了したら、最大値を出力します。
ENDブロックで最大値を出力すればOK。
END{
print "最大値=" max
}
