多次元配列 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
こんな感じ.
ちゃんと多次元っぽくアクセスできてます. なんて便利なんだ!!