2016年1月23日土曜日

gawk で文字列 "01" の比較でハマった

長年(20年以上) AWK を使っていて、わかってるつもりでしたが、文字列が暗黙に数値として扱われる際の落とし穴にハマりましたので、備忘録です。以前にも、このパターンに悩まされた記憶があるんですが、忘れたころにふたたびバグってしまいました。
BEGIN {
    s="01 02"
    split(s, ss)
}
{
    for (i in ss) {
        if ($1 == ss[i]) {
            printf "%s == %s\n", $1, ss[i]
        } else {
            printf "%s != %s\n", $1, ss[i]
        }
    }
}
[root@hoge tmp]# echo 01 | gawk -f test_string_01.awk 
01 == 01
01 != 02
[root@hoge tmp]# echo 1 | gawk -f test_string_01.awk 
1 == 01
1 != 02
$1 が 1 の場合には、if ($1 == ss[i]) において ss[i] が数値として扱われ、文字列の "01" が暗黙に数値の 1 として比較が実行されるのだと思います。次のように修正(C言語のキャストっぽく修正)することで、意図した動作になりました。
BEGIN {
    s="01 02"
    split(s, ss)
}
{
    for (i in ss) {
        if ($1 == ""ss[i]) {
            printf "%s == %s\n", $1, ss[i]
        } else {
            printf "%s != %s\n", $1, ss[i]
        }
    }
}
[root@hoge tmp]# diff -u test_string_01.awk test2_string_01.awk 
--- test_string_01.awk 2016-01-23 20:06:54.537647508 +0900
+++ test2_string_01.awk 2016-01-23 20:25:23.543167642 +0900
@@ -4,7 +4,7 @@
 }
 {
     for (i in ss) {
-        if ($1 == ss[i]) {
+        if ($1 == ""ss[i]) {
             printf "%s == %s\n", $1, ss[i]
         } else {
             printf "%s != %s\n", $1, ss[i]
[root@hoge tmp]# echo 01 | gawk -f test2_string_01.awk 
01 == 01
01 != 02
[root@hoge tmp]# echo 1 | gawk -f test2_string_01.awk 
1 != 01
1 != 02
ちなみに、別実装(nawk, mawk)でも、同様の結果でした。
[root@hoge tmp]# echo 01 | nawk -f test_string_01.awk 
01 != 02
01 == 01
[root@hoge tmp]# echo 1 | nawk -f test_string_01.awk 
1 != 02
1 == 01
[root@hoge tmp]# echo 01 | mawk -f test_string_01.awk 
01 != 02
01 == 01
[root@hoge tmp]# echo 1 | mawk -f test_string_01.awk 
1 != 02
1 == 01
nawk, mawk では、for (i in ss) の順序が、gawk とは違うようですが、今回の問題の比較部分は同様に意図しない動作になります。そして、同じ修正で、意図した動作になります。
[root@hoge tmp]# echo 1 | mawk -f test2_string_01.awk 
1 != 02
1 != 01
[root@hoge tmp]# echo 1 | nawk -f test2_string_01.awk 
1 != 02
1 != 01

こういうことも、たまにはあるけども、いやー AWK って本当にいいもんですね。って思います。
この 20年 どんだけお世話になったことか。費用対効果(学習コストに対する成果)が抜群じゃないかなと。手短に手早く書いて、あっという間に結果を得られることがしばしばです。

0 件のコメント:

コメントを投稿

人気ブログランキングへ にほんブログ村 IT技術ブログへ