シェルとシェルスクリプト 4 条件分岐、繰り返し、サブルーチン
条件分岐
プログラミングでは、条件に剃って挙動を切り替える 「 条件分岐 」 を多用する。シェルスクリプトでも利用することができる。
if 文
比較などによる条件分岐を行う場合はif 文を利用する。
$ if 条件式1 then ... elif 条件式2 ... else ...fi
elif と else は省略可能である。 elif は別の条件で判断したい場合に利用する。 else は条件に当てはまたなかった場合に実行される。if 文は fi で終了する。
条件式 if 文で利用される条件式
演算子 | 比較内容 |
---|---|
a == b | a と b が等しければ真 |
a != b | a と b が等しくなければ真 |
数値比較を行う演算子
演算子 | 比較内容 |
---|---|
a -eq b | a と b が等しければ真 ( equal to ) |
a -ne b | a と b が等しくなければ真 ( not equal to ) |
a -ge b | a が b 以上であれば真 ( greater than or equal to ) |
a -le b | a が b 以下であれば真 ( less than or equal to ) |
a -gt b | a が b より大きい値であれば真 ( greater then ) |
a -lt b | a が b 未満であれば真 ( less than ) |
ファイル属性の確認
ファイル属性の確認は次のように行う。
$ if test -d パス ; then ...
-d の部分がファイル属性確認の演算子にあたる。 -d はディレクトリであるかの判定を行うので、この if 文全体で、 「 パスがディレクトリであれば真の値を返す 」 という条件式になる。
ファイルの属性確認演算子は以下のようなものが利用できる。
演算子 | 内容 |
---|---|
-f ファイル名 | 通常ファイルなら真 |
-d ファイル名 | ディレクトリなら真 |
-e ファイル名 | ファイルが存在するなら真 |
-L ファイル名 | シンボリックなら真 |
-r ファイル名 | 読み取り可能ファイルなら真 |
-w ファイル名 | 書き込み可能ファイルなら真 |
-x ファイル名 | ファイルが存在して、実行権限があれば真 |
-s ファイル名 | サイズが0より大ければ真 |
なお、test コマンドは [] を使って記述することもできる。
$ if [ 条件節 ]; then ... $ if test [ 条件節 ] ; then ...
複数の条件式を重ねる
条件分岐指定いる場合、複数の条件を重ねることができる。条件Aと条件Bが同時に成立してい必要がある時は 「 条件Aかつ条件Bが成立 」 ということで、論理積 ( =AND ) が用いられる。
同じく、 「 条件Aもしくは条件Bが成立 」 の場合は論理和 ( =OR ) が用いられる。シェルスクリプトにおいて、論理積、論理和の書き方は2通り存在する。
論理積
論理積は -a を用いる場合と、 && を用いる場合がある。
$ [ 条件A -a 条件B -a 条件C ] ... $ [ 条件A ] && [ 条件B ] && [ 条件C ] ] ...
-a と && は、それぞれ [ ] の内側か外側かで、使われ方が変わることに注意する。
論理和
論理和を表す記号は -o と || である。
$ [ 条件式A -o 条件式B -o 条件式C ]... $ [ 条件式A ] || [ 条件式B ] || [ 条件式C ]...
論理積の時と同様に -o と || はそれぞれ [ ] の内側か外側かで使われ方が変わる。
一体多の条件式
一体多の分岐を行うことを考えてみる。 if 文を用いた場合、一体多の分岐は以下のようになる。
if 条件式 then elif 条件式 then elif 条件式 then fi
シェルスクリプトでは、case 文が用意されており、一体多の分岐が記述できるようになっている。
case 変数 in 値A) 処理1;; 値B) 処理2;; esac
変数の値が値Aである時、処理1が実行される。最後は case 文の逆からの記述である esac で終わることが重要である。値はパイプ ( | ) で区切って複数指定することもできる。
実行例
$ vi case.sh ( インサートモードで以下を入力 ) #!/bin/bash case $1 in a|A) echo "引数にaまたはAが入力されました";; b|B) echo "引数にbまたはBが入力されました";; esac
シェルスクリプトを実行する。
$ ./case.sh a 引数にaまたはAが入力されました $ ./case.sh b 引数にbまたはBが入力されました
また、どの値にもマッチしなかった場合の処理を記述するには、値にアスタリスク ( * ) を用いる。
実行例
$ vi defaultcase.sh ( インサートモードで以下を入力 ) #!/bin/bash case $1 in 1) echo "引数に1が入力されました";; 2) echo "引数に2が入力されました";; *) echo "1,2以外が入力されました";; esac
シェルスクリプトを実行する。
$ ./defaultcase.sh 1 引数に1が入力されました $ ./defaultcase.sh 2 引数に2が入力されました $ ./defaultcase.sh 0 1,2以外が入力されました ( どの条件にもマッチしない場合、値 * の処理が実行される )
繰り返し
プログラミングにおいて、条件分岐と同じくらい重要な機構が繰り返しである。同じ処理を繰り返し行い、ある条件が成立した時に終了する、という形式が用いられる。シェルスクリプトで用いられる繰り返しは以下の3通りである。
for 文
for 文は値を列挙し、それを対象に処理を繰り返す。
$ for 変数 in 値のリスト do 処理 done
値のリストとは、文字を羅列したものもあれば、実行結果を使うこともできる。
実行例
$ for i in a b c d for> do for> echo $i for> done a b c d
これは、値のリストとして、a b c d が渡され、i = a を行い echo $1 、次に $1 、次に...を繰り返した結果である。値のリストとしてコマンドの実行結果を使うことができ、以下のように、i に ls の実行結果を代入してループが実行される。
$ for i in `ls` for> do for> echo $i for> done Applications Desktop Documents Downloads HTML CSS JavaScript ...
while/until 文
while 文は条件が成立している間ループを繰り返す ( 条件が成立しなくなったら終了 ) という処理で利用される。
until 文はそれの反対で条件が成立していない間ループを繰り返す ( 条件が成立したら処理を終了 ) という用途で使われる。
$ while 条件式 do 処理 done $ until 条件式 do 処理 done
C言語の for 文のようなループ分をシェルスクリプトで実現するには、expr コマンドを用いてループカウンタ用の変数をインクリメント ( またはデクリメント ) しながら、while/until 文で処理を行う。
実行例
$ vi loop.sh #!/bin/bash count=1 while [ $count -le 10 ] do echo この処理は $count 回実行されました count=`expr $count + 1` done
count=1 で、カウンタ用の変数 count に初期値1を設定する。while [ $count -le 10 ] で、シェル変数 count が10以下の間、処理を繰り返す。
シェルスクリプトを実行
$ ./loop.sh この処理は 1 回実行されました この処理は 2 回実行されました この処理は 3 回実行されました この処理は 4 回実行されました この処理は 5 回実行されました この処理は 6 回実行されました この処理は 7 回実行されました この処理は 8 回実行されました この処理は 9 回実行されました この処理は 10 回実行されました
select 文
select 文はユーザに対して数値による入力を促す。
$ select 変数 in リスト do 処理 done
実行例
$ select name in "apple" "banana" "orange" select> do select> echo "You selected $name"; select> done 1) apple 2) banana 3) orange ?# 1 You selected apple ?# 2 You selected banana ?# 3 You selected orange ( control + c で終了する )
繰り返しの制御
break や continue を用いることで、繰り返しを制御することができる。break は繰り返しを終了して、continue は繰り返しの先頭に戻る役割がある。
実行例
$ vi sample.sh ( インサートモードで以下を入力 ) while true do echo "Continue? (y/n)" read input case $input in n) break ;; y) continue ;; *) echo "Please input y or n." ;; esac done
シェルスクリプトを実行する
$ ./sample.sh Continue? (y/n) y ( y を入力する ) Continue? (y/n) ( 繰り返しの先頭に戻る ) a ( a を入力する ) Please input y or n. ( どの値にもマッチしなかった場合の処理が実行される ) n ( n を入力すると終了する ) $
サブルーチン
プログラミングをする上で、一連の処理をまとめて、再利用できるようにしたものを、サブルーチンと言う。サブルーチンは言語により様々な呼ばれ方をされていて、シェルスクリプトでは関数と呼ばれている。
関数
関数は、引数と呼ばれるデータを与え、処理をして結果を返すという機能の集まりである。
$ function 関数名 { 処理 } $ 関数名() { 処理 }
両者ともに働きは同じである。引数は、実行時に関数名に続けて記述する。引数は関数の内部で、$1 、 $2 で参照することができる。
return 文
シェルスクリプトの関数で、結果を返すときはreturn 文を実行する。
$ return 変数名
return 文を実行すると、関数内での処理はそこで終了し、変数が関数に呼び出され元に戻される。