数値からなる行列を表す文字列が与えられたとき、その行列の行と列を返してください。
例えば、次のように改行が埋め込まれた文字列が与えられたとします。
9 8 7
5 3 2
6 6 7
これは、次の行列を表しています。
1 2 3
|---------
1 | 9 8 7
2 | 5 3 2
3 | 6 6 7
このとき、コードは次の2つを出力できるようにします。
例の行列の行は次のとおりです。
そして、その列は次のとおりです。
これは、解答が"main"スクリプトではない最初の演習です。 目標は、他のawkプログラムに読み込ませる関数のライブラリを書くことです。 この演習では、興味深い新しい概念をいくつか見ていきます。
以下で"(gawk)"というタグが付いているセクションは、GNU awk固有の拡張機能です。
この演習では、データをメインの入力ストリームからではなく、ファイルから読み込みます。
Gnu awkマニュアルのgetlineについて、特にGetline/FileとGetline/Variable/Fileの形式を読んでみましょう。
この解答を実装するには、2次元配列が使えるかもしれません。 GNU awkには、それを表す方法が2つあります。
テストファイルにある@includeディレクティブに注目してください。
これは、指定したファイルを読み込んで評価するようgawkに指示します。
awkの変数はすべてグローバルです(関数の仮引数だけは、その関数内でローカルです)。
特にサードパーティのライブラリを読み込むときは、名前が衝突する可能性が高くなります。
名前空間は、変数をどこに保存するかを区切る仕組みです。
演習のファイルにある@namespaceディレクティブに注目してください。
デフォルトの名前空間の名前は"awk"です。 デフォルトの名前空間があることで、別の名前空間にある関数の中から、awkの組み込み関数を呼び出せます。
配列の仮引数は参照渡しで渡されます。 関数内で加えられた配列の変更は、呼び出し側からも見えます。
配列以外の仮引数は値渡しで渡されます。
_型なし_の仮引数については、関数がそれをどう扱うかによって変わります。
詳しくは、マニュアルのPassing Function Arguments by Value Or by Referenceに書かれています。
関数スコープの(ローカルな)変数は、「値渡し」の仮引数を使うと作れます。 関数に渡す値が、並んでいる仮引数の数より少なくてもエラーにはなりません。余った仮引数は、使われるまで「型なし」のままです。 これらには、関数内でスカラー値を代入でき、その値はグローバルな名前空間には保存されません。
慣例として、関数のシグネチャでは、受け取る仮引数が先に並び、そのあとに空白を挟んでローカルな仮引数が続きます。 例を示します。
function add(a, b, total) {
# here, `typeof(total)` is "untyped"
total = a + b
# now, `typeof(total)` is "number"
return total
}
BEGIN {
sum = add(5, 10)
print sum # 15
print typeof(total) # untyped, meaning "total" is unused in this scope
}