多次元配列 Hack?

AWK
有名なスクリプト言語(今風の言い方だとLL).昔ながらの行指向のデータ(特にcvsとか)の処理に非常に強いです.

Cライクな文法なので,sedやexで苦労した人にオススメ!w 某会議室のログを整形…(という謎の憧憬もあったり)

まぁワンライナー書くのには便利なのですが,データ構造は貧弱で,言語組み込みの連想配列くらいしかありません.(キーもバリューも文字列です)
おまけにこの配列,多次元配列が構成できません./(^o^)\

たとえば…

#!/usr/bin/gawk -f
BEGIN { map["a"]["b"] = 0 }

こんな風に書くと,

 gawk: ./test.gawk:4:    map["a"]["b"] = 0
 gawk: ./test.gawk:4:            ^ syntax error

エラーですね.

でもでもっ!

多次元配列が使いたいこともあるわけです!
そこで,キーの連結/分解を使って擬似多次元配列を実現します.
ラクリは単純で,キーとなる文字列を適当な文字で次元の数だけ連結した物を実際のキーとして使用します.
なので, v["foo"]["bar"]のようにアクセスしたい場合,

 v["foo","bar"] = "hoge"

と書いてキーを「"foo","bar"」として擬似的な二次元配列とするわけです.


しかしこのまま愚直にキーを列挙すると,連結した(単一の)キーが出てきてしまい不便です.
これは組み込みで提供される,split関数を使って解決します.

for( i in myMap ){
    split( i, js, SUBSEP )
    print "index1=" js[1] " index2=" js[2] " value=" myMap[js[1],js[2]];
}

myMapは二次元のユーザデータです. 単にfor文を使うだけだと'連結済みキー'の状態なので,
これをsplitで分割します.上の例ではiをSUBSEP(標準で使用)で区切って配列jsに入れてます.

通して使うと

#!/usr/bin/gawk -f
BEGIN {
	map["e0","e1","e0"] = 0
	map["e0","e1","e1"] = 1
	map["e0","e1","e2"] = 2
}
END {
	for( i in map ){
		split(i,is,SUBSEP)
		print "map[" is[1] "," is[2] "," is[3] "] = " map[is[1],is[2],is[3]]
	}
}
$ echo "" | ./test.gawk
map[e0,e1,e0]=0
map[e0,e1,e1]=1
map[e0,e1,e2]=2

こんな感じ.
ちゃんと多次元っぽくアクセスできてます. なんて便利なんだ!!

まとめ

PerlRubyを覚えようと思った.