[シェルスクリプト]シェルスクリプトで関数を使い分ける

2016年9月12日月曜日

bash linux unix シェルスクリプト

シェルスクリプトはインタプリタで1行ごとに順に解釈されていくから、関数を実行する前にその関数の定義が登場しなければいけない。
それはいいんだけど、本当に "実行する前に" ということがどういうことか、ちゃんと分かってなかった。

以下のようにfunc1からfunc2を呼び出しているとしよう。

#!/bin/sh
func1 () {
  echo 'func1'
  func2
}

func2 () {
  echo 'func2'
}

func1

これだと一見、func1よりもfunc2を先に定義しないといけないんじゃないの?って気になる。
でも、そうじゃない。
関数の定義が出現したときに行われるのは、関数リストに関数を追加することだけで、中身を見るのは関数が実行されるときだ。

実際に1つずつやってみよう。
$ declare -f
$ func1 () { echo 'func1'; func2; }
$ declare -f
func1 ()
{
  echo 'func1'
  func2
}
$ func2 () { echo 'func2'; }
$ declare -f
func1 ()
{
  echo 'func1'
  func2
}
func2 ()
{
  echo 'func2'
}

関数が順に追加されているのがわかるね。
だから、func.shでは11行目でfunc1を呼び出した時点ではfunc1,func2ともに関数リストに追加された後だから、func1の中からfunc2を呼び出せるんだね。

これを応用すると、条件によってfunc2を切り替えることにより、func1の挙動を切り替えることができる。
if ...
then
  func2 () {
    echo 'if条件合致'
  }
else
  func2 () {
    echo 'if条件非合致'
  }
fi

func1
この手法をやりすぎると、よくわからないスクリプトになってしまいそうだけど、環境差の吸収やデバッグ時には使えるかな。