awk で最大値と最小値

教えてR2!! the 3rd に「ちなみにawkにmaxがないのはなぜ?」と書かれてあるのは一瞬納得しかけたけど、awk としての自由度が減るケースもあるのではないでしょうか?

例えば、アクションで変数に入れてアクションの中で最大値や最小値を計算させるというケースが意外に多いのではないでしょうか?

#! /usr/bin/gawk -f
# max_min.awk

{
    var = $0;

    if (max == "") {
        max = var;
    }

    if (max < var) {
        max = var;
    }

    if (min == "") {
        min = var;
    }

    if (min > var) {
        min = var;
    }
}

END {
    print "min = " min;
    print "max = " max;
}

こうした使い方は比較的自由度が高いので、良く使われます。 これを使うには以下のようにします。

$ seq 10 | gawk -f max_min.awk
min = 1
max = 10

上記のように数字を格納すれば最大最小が求まりますが、awk では文字列比較も数値比較も同じなので単純に max, min という名前で awk の組み込み変数にしてしまうのは少し違和感があります。

また、関数化できそうなケースとしては一度配列に入れてしまいます。

#! /usr/bin/gawk -f
# max_min.awk

{
    line[NR] = $0;
}

END {
    print "min = " min(line);
    print "max = " max(line);
}

# max
function max(arr) {
    for (i in arr) {
        val_max = arr[i];
        break;
    }

    for (i in arr) {
        if (val_max < arr[i]) {
            val_max = arr[i];
        }
    }

    return val_max;
}

# min
function min(arr) {
    for (i in arr) {
        val_min = arr[i];
        break;
    }

    for (i in arr) {
        if (val_min > arr[i]) {
            val_min = arr[i];
        }
    }

    return val_min;
}

上記のようにすることで関数化することができます。

$ seq 10 | gawk -f max_min.awk
min = 1
max = 10

Makefile 中の $

そういえば「makefileの中でawkを使う場合、$1とかがうまく認識されない」は以下のようにします。

$ cat Makefile
all:
        seq 10 | awk '{print $$0}'

実行させると以下のようになります。

$ make
seq 10 | awk '{print $0}'
1
2
3
4
5
6
7
8
9
10

16 進数変換

10 進数を N 進数に基数変換するあたりを見ていただけると分かると思います。

組み込み関数の少なさは awk の良さでもあり、欠点でもありますが、それを補う意味でもこの AWK ならどう書く? の需要はあると思っています。 もし、取り上げてほしい話題などがあれば、どしどし意見をください。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png