次へ: 5 入力チェック関数 上へ: 4 課題文の作成 前へ: 4.3 文字列値配列の生成 (PDF ファイル: awk2.pdf)


4.4 ユーザ定義関数化

ここまでの内容を一つの関数にしてみましょう。
  function mkkadai(M,  j,x,N,a,s)
  {
      s=""
      srand()
      N=split("abcdefghijklmnopqrstuvwxyz      ",a,"")
      for(j=1;j<=M;j++){
          x=int(rand()*N)+1
          s = s a[x]
      }
      return s
  }
これを少し説明します。

function mkkadai(M,...) は、 これが mkkadai という名前の関数の定義ブロックであることを意味します。 スクリプトのこの部分はすぐに実行されるわけではなく、 実行ブロック内でその名前の関数が使われたときに、 この定義部分が実行されます。

M,j,x,N,a,s は引数を意味しますが、 この関数の場合実際に引数として与えられるのは $M$ だけで、 後は引数というよりもむしろ関数内部でのみ通用する「局所変数」です。 ここは、AWK 独特のテクニックで、詳しいことは 付録 A をご覧ください。 とりあえずは、AWK の関数定義では、

  function 関数名 (引数,...,引数,   局所変数,...,局所変数)
  {
      関数本体
  }
と書くのだと覚えておけばいいでしょう。 引数と局所変数の間はタブやスペースを入れて区別して書くと見やすいと思います。 ここに書かれていない変数を関数内部で使用すると、 それは局所変数ではなく AWK スクリプト全体で通用する外部変数 (大域変数) と見なされます。

srand() がこの関数の中に入っていますが、 この関数 mkkadai() はプログラムで 1 回しか呼ばないということで ここに入れてあります。 しかし、この関数が複数回呼びだされる可能性がある場合は srand() ここには入れずに、 BEGIN{} ブロックの先頭で呼ぶようにした方がいいでしょう。

return s は、$s$ を関数の値として返す命令で、 よって $s$ に 40 文字 (ここでは $M$ 文字) の文字列を作っています。 $s$ の作成には文字列の連結を使っていますが、 AWK で文字列を連結する方法は 2 種類あって、

ということになっています。例えば、
s="a" "b","c" $\Rightarrow$ s="ab c"
となります。

この関数では最初に s = "" と空文字列として、 s = s a[x] で、$s$ の最後に a[x] を連結しているので、 a[x]$M$$s$ の後ろに連結していくことで $M$ 文字分の文字列ができることになります。

文字列の長さは 40 と固定せずに引数として $M$ としましたが、 これは後でこの数字を変更したい場合のことを考えてこのようにしています。

もし、関数内で $M$ でなくて 40 と書いた場合、 その数値を後で変更しようと思ったら 関数の中の 40 をすべて変更していかなければいけませんが、 このように変える可能性のある数字を引数とすれば、 この関数を呼びだすときに引数を一つ変えるだけで済みます。 これは、独立性や汎用性の高いサブルーチンを作るときに 標準的に行われる方法ですので、 覚えておくといいでしょう。

そういう点からすると、実は "abc..." の文字列も この中に書かずに、引数として与えたり 外部変数としたりする方が汎用性は高くなります。 例えば、アルファベットの大文字を追加したり、記号を追加したり、 または課題のレベルに従って文字を増やしたりしたい場合は、 この文字列を変える必要がありますが、 その場合この文字列を関数の外に出してしまって それを引数として与える仕組みにすれば変更は容易になります。


次へ: 5 入力チェック関数 上へ: 4 課題文の作成 前へ: 4.3 文字列値配列の生成
竹野茂治@新潟工科大学
2006年4月27日