Sample Site

GAWK 動的に多次元配列を生成する

  こんな表があったら Part 1

gen_array_sample.jpg

(注)以下のスクリプトは、GAWK 4.0 以降でないと動きません。
この表は例えば foo[x][y][z][t] = value と4次元配列を表現しています。
このファイルを GAWK4 で読み込み、多次元配列 (実際には配列の配列ですし、中身はハッシュですが、このように呼ぶことにします) として格納してしまおうという試みです。


Homeへ戻る

awk_gen_array.awk

1 : #. arrays of arrays dynamically generate; 2 : # 配列の配列を動的に生成する手法を検討する 3 : #. Action; 4 : { 5 : aformat(); 6 : array_entry(foo, _arexp, _value); 7 : } 8 : #. END; 9 : END { 10 : PROCINFO["sorted_in"] = "@ind_num_asc"; 11 : print_array(foo, "foo"); 12 : }

13 : #. aformat();表の多次元配列のインデックス群と値を中間処理 14 : function aformat( i) { 15 : _arexp = ""; 16 : _value = $NF; 17 : if (NF == 1) print "line:" NR " inappropriate input"; 18 : else if (NF == 0); 19 : else { 20 : for (i = 1; i < NF - 1; i++) _arexp = _arexp $(i) " "; 21 : _arexp = _arexp $(NF - 1); 22 : } 23 : }

24 : #. array_entry();動的に多次元配列を作成 25 : function array_entry(a, arexp, value, step) { 26 : if (!step) { 27 : _dim = 0; 28 : delete _tmp; 29 : _dim = split(arexp, _tmp, / /); 30 : if (!_dim) return 1; #scalar or null skip 31 : if (_dim == 1) { a[arexp] = value; return 0; } 32 : } 33 : if (step == _dim - 2) { 34 : a[_tmp[_dim - 1]][_tmp[_dim]] = value; 35 : return 0; 36 : } 37 : a[_tmp[step + 1]]["dummy"]; 38 : array_entry(a[_tmp[step + 1]], "", value, step + 1); 39 : delete a[_tmp[step + 1]]["dummy"]; 40 : }

41 : #. print_array();多次元配列の内容をすべて書き出す 42 : function print_array(a, an, e, i) { 43 : for (i in a) 44 : if (isarray(a[i])) print_array(a[i], an, (e "[" i "]")); 45 : else print an (e "[" i "] = ") a[i]; 46 : }

実行結果 Part 1

gen_array_ext01.jpg


  こんな表があったら Part 2

Part1 では配列の次数が一定でしたので、次はランダムな次数で行ってみましょう。スカラーが混じったり、空白行も入れてみます。さらに、同一配列に違う値を代入してみます。

gen_array_sample02.jpg

実行結果 Part 2

gen_array_ext02.jpg


  こんな表があったら Part 3 エラーを起こす

gen_array_sample03.jpg

実行結果 Part 3

gen_array_ext03.jpg


1行目で foo[1][1][1] = "BEGIN" が格納され、この際 foo[1][1][1] はどうやらスカラーの扱いになるらしいのです。スカラーとなった foo[1][1][1] を2行目で配列として、(foo[1][1][1])[2] すなわち (scalar)[2] という感じに使おうとしているので、致命的なエラーとなるようです。
よく考えると当然なんです。配列の配列なので値が代入された時点で、その最も下位のインデックスは、さらに下位の配列を持つことができません。foo[1] は配列を持っていて、foo[1][1] も配列を持っています。しかし、foo[1][1][1] は配列を持っていない。持っているのは、値 "BEGIN" だということです。なので、この場合 foo[1][1][1][2] というのはあり得ない、だから致命的エラーが出るというわけです。

このスクリプトは以前某掲示板に投稿したことがあります。何に使うかわからないスクリプトではありましたが、配列の次数を動的に増やすというお題がとても興味深い内容でしたので、考えてみました。でも、いまだに何に利用できるのかわかりません。