5. シェルプログラミング(2)  

4. では主に関数と変数の処理を取り扱った. ここでは,より本格的なプログラミングを実現するために フロー制御構造について述べる. これは if, for, while 等といったプログラムの実行の流れを制御する機構である.
 
<-- 「4. シェルプログラミング(1)」へ戻る 目次へ戻る 「6. コマンドラインオプションと定義済み変数」へ進む -->


5.1 if / else

5.2 条件の評価

5.3 for

5.4 case

5.5 select

5.6 while と until


5.1 if / else 5.2 条件の評価

5.3 for

前述した if 構造は条件分岐を実現する機能であった. これに対し,繰り返しを実現する構造の一つがこの for 構造である.

C 言語の for 文に慣れている人は,ある文を 10 回繰り返すといった構造を思い浮かべるかも知れないが, bash での for 文はこれとは違う. 指定されたリストに沿って処理を繰り返すものである.

for 構造の構文は

for  name  in  list
do
      $name  を利用する文
done
in  list  は省略可能で, 省略した場合は "$@" がデフォルトの値として設定される. これは前述した 位置パラメータ の一種で,コマンドライン引数のリストになる.

(例) aaa, bbb, ccc という文字列を順に表示する

for  name   in   "aaa"  "bbb"  "ccc"
do
      echo   $name
done
(例) コマンドライン引数を順に表示する
for  args
do
      echo  $args
done
5.4 case
Pascal の case 文や C の switch 文を連想してもらえば分かりやすいと思うが, 場合分けの構造を実現するためのものである. その構文は
case 条件式 in
   パターン1)
            処理1 ;;
   パターン2)
            処理2 ;;
           .........
esac
という構造になっており, 条件式に対して パターン1 が適合した場合は 処理1を実行, パターン2 が適合した場合は 処理2を実行,.... といった具合になる. なお,C や Pascal とは異なり, これらのパターンには 文字列やワイルドカードを含むパターンが利用 できる.

(例)コマンドライン第1引数が .c で終るときは .c を除く部分をオブジェクトの名前として gcc でコンパイルし, .java で終るときは javac でコンパイルし, いずれの場合でもない場合は "unknown type" と表示する.

case $1 in
       *.c )
            gcc -o ${1%.c} $1 ;;
       *.java )
            javac $1 ;;
       * )
            echo "unknown type" ;;
esac
(C 言語での default 文のように) いずれの場合にも当てはまらなかった時のデフォルト処理を指定するための特別な命令は用意されていないが,上のようにパターンに * を用いればよい.

5.5 select

これは簡単なメニューをすばやく生成することのできる優れた機能である.
指定されたリストを番号付きで表示し,ユーザに番号を入力させる. そこで,指定された番号の内容が変数に格納され, それぞれの処理へと移行するというものである.
つまり,シェルスクリプトでありながらユーザとの簡単な対話が可能なのである.

select の構文は for のそれに酷似しており

select name in list
do
   $name を利用する文
done
となっている. (for が select  に代わっただけである.) これも in listは省略可能で, 省略した場合は "$@" がデフォルトの値として利用される.

(例)which host ? と表示して, ユーザにホスト番号を指定させる. そして,指定されたホストへの rlogin を試みる.

PS3='which host ? '
select  loginhost  in  edu1 edu2 edu3 edu4 edu5 abc xyz
do
     case  $loginhost  in
        edu[1-5] )
           rlogin -l ユーザ名 "$loginhost".edu.foo.bar.ac.jp ;;
        abc | xyz )
           rlogin -l ユーザ名 "$loginhost".hoge.foo.bar.ac.jp ;;
        * )
           echo "invalid number" ;;
     esac
     break
done
(ユーザとの対話に利用するプロンプトは PS3 に指定する.)
(この select 文を終了させるために break 文を使っている. select 文は処理を無限に繰り返す設計になっているため,これが必要となる.)
5.6 while と until
if 文では条件が真か偽かで場合分けを行い, それぞれ用意された処理を実行するが,これを繰り返すようにしたのが while や until である. while の構文は
while 条件
do
   処理
done
条件 が真である限り 処理 を繰り返す. 逆に,条件が偽である限り繰り返すのが until で
until 条件
do
   処理
done
という構文になっている. これは 「コマンドが正しく実行されるまで処理を実行し続ける」 といったシチュエーションに有効である. (条件 にそのコマンドを書けば異常終了したときに 処理 が実行され,再び条件に戻る.)

(例)コピースクリプト

until cp $1 $2
do
   echo "waiting..."
   sleep 5
done
これでは $1 を $2 にコピーすることを試み, 失敗した場合は 5 秒待って再度試みる.