シェルスクリプトで再帰する
ふと気になって、関数の再帰呼び出しをしらべてみました。OSはHP-UX 11iです。
#!/usr/bin/ksh typeset -i index function recursive_function { let index=${index}+1 if [ $index -eq 10 ]; then : # ヌルコマンドで関数を抜ける else echo $index recursive_function fi } echo "start" recursive_function echo "end" exit 0
次にスクリプト自分自身を呼び出してみました。
#!/usr/bin/ksh typeset -i index let index=${index} export index # サブプロセスに引き継ぐため if [ $index -eq 1 ]; then # 初回だけわざわざ区別 echo "start" fi if [ $index -eq 10 ]; then echo "end" else echo $index ./recursive_sh.ksh fi exit 0
実行結果はどちらも
start 1 2 3 4 5 6 7 8 9 end
です。
シェルスクリプト自身を呼び出す方は、開始と終了のメッセージを出すように書こうとしただけでスパゲッティ気味ですね。ほかに、スクリプト自身を呼び出す方は0以外で初期化しようとすると面倒ですね。
次に何回まで再帰できるかを試してみました(コード中の10を適当に変更)。いろいろ試してみたところ、関数を使った方は128回を越えたところで、エラーになりました。
./recursive_function.ksh[17]: recursive_function: recursion too deep
スクリプト自身を呼び出す方は、実行が関数を使う方よりずっと遅く、かなりの回数でも大丈夫なようで途中でキャンセルしました。
128回の再帰呼び出しで実行時間を比較してみると、予想通りかなりの差がありました。同一プロセスで実行されているかどうかということですよね。
$ time (recursive_function.ksh 1>/dev/null) real 0m0.01s user 0m0.01s sys 0m0.01s
$ time (recursive_sh.ksh 1>/dev/null) real 0m0.96s user 0m0.18s sys 0m0.79s