MPFRによる拡張
GNU AWKをソースからビルドする際、GNU MPFRとGNU MPがすでに導入されている場合には、自動的にMPFR拡張が導入されます。導入されているかどうかは、gawkのバージョンを表示することで分かります。次のように表示されたバージョンは、この拡張が組み込まれています。
$ gawk --version GNU Awk 4.1.60, API: 1.1 (GNU MPFR 3.1.2, GNU MP 5.1.2)
$ echo 53 | gawk '{print 2 ^ $1 - 1}' 9007199254740991 $ echo 54 | gawk '{print 2 ^ $1 - 1}' 18014398509481984
2のべき乗は必ず偶数になるため、これから1を引いた数は奇数になるはずですが、2 ^ 54 - 1が偶数になっていることが分かります。これはgawkが53ビット演算までしか正確に計算できていないということです。そこで今度はMPFRを用いた拡張を試してみましょう。
$ echo 54 | gawk -M '{print 2 ^ $1 - 1}' 18014398509481983
検算はbcコマンドで行ってみましょう。
$ echo '2^54-1' | bc 18014398509481983
$ gawk 'BEGIN {x = 1.0e-400; print x + 0}' 0 $ gawk -M 'BEGIN {x = 1.0e-400; print x + 0}' 1e-400
AWKでls
AWKはシェルを介した他のコマンドとの相性が良いため、「シェル芸勉強会」の中でも毎回用いられるコマンドの1つです。しかし、基本的なコマンドほどOS間で出力形式が微妙に異なるため、悩まされたことも多いのではないかと思います。そこで、lsコマンドそのものを作ってみます。
@load "filefuncs" BEGIN { passwd = "/etc/passwd"; group = "/etc/group"; FS = ":"; while (getline < passwd > 0) { user_of[$3] = $1; } close(passwd); while (getline < group > 0) { group_of[$3] = $1; } close(group); for (i = 1; i <= ARGC - 1; i++) { stat(ARGV[i], stat_data_of); m_time = strftime("%Y-%m-%d %H:%M", stat_data_of["mtime"]); printf("%s %3d %8s %8s %9d %s %s\n", stat_data_of["pmode"], stat_data_of["nlink"], user_of[stat_data_of["uid"]], group_of[stat_data_of["gid"]], stat_data_of["size"], m_time, stat_data_of["name"]); } }
$ touch a b $ gawk -f ls.awk a b -rw-r--r-- 1 hi_saito hi_saito 0 2014-11-03 15:18 a -rw-r--r-- 1 hi_saito hi_saito 0 2014-11-03 15:18 b $ ls -l --time-style=long-iso a b -rw-r--r-- 1 hi_saito hi_saito 0 2014-11-03 15:18 b -rw-r--r-- 1 hi_saito hi_saito 0 2014-11-03 15:18 a
このようにGNUのcoreutilsのlsコマンド(--timestyle=long-isoオプション相当)に近い出力を得ることができました。