| 6. コマンドラインオプションと定義済み変数 | 
| ここでは (UNIX コマンドにあるような)
   コマンドラインオプションをもったスクリプトを作成する方法について紹介する. また, これまで紹介した変数はいずれも文字列をデータ型にしたものであったが, 数値の処理方法についても述べる. | ||
| <-- 「5. シェルプログラミング(2)」へ戻る | ↑ 目次へ戻る | 「7.その他」へ進む --> | 
6.1 コマンドラインオプション
6.2 変数の属性設定6.3 整数型変数と数値演算
いま,2 つの引数をとるスクリプトを考える. ただし,それらの引数を与える前に -o というオプションを付けることも許されているものとする. その場合,
とすることで, 常に $1 を第1引数, $2を第2引数として処理できるように思えるが, 位置パラメータ $1, $2 には 代入は許されていない ためエラーとなり,期待通りの結果にならない.
if [ $1 = -o ] then ...... オプションに対する処理 ...... 1=$2 <---エラーになる 2=$3 <--- fi
また,オプションが複数用意されている場合, 同様に複数回の shift が必要となる. shift 文を繰り返し記述してもよいが, shift にずらす回数を指定することもできる. 例えば,
if [ $1 = -o ] then ...... オプションに対する処理 ...... shift fi
と記述すると,一度に 3 回分 shift を実行できる.
ここでは複数のオプションが許されている場合の定番となるスクリプトを 示す. 以下のスクリプトでは -a, -b, -c の 3 種類のオプションが許されており, そのいずれでもないオプション ('-'の付いた文字列) が指定された場合は使い方を表示して exit する.
while [ -n "$(echo $1 | grep '-' )" ] do case $1 in -a ) オプション -a の処理 ;; -b ) オプション -b の処理 ;; -c ) オプション -c の処理 ;; * ) echo '使い方....' exit 1 esac shift done
まず,$(...) による コマンド置換 を用いて $1 の内容と '-' とのマッチング (grep コマンドによるもの) を行い,その結果が NULL でない (-n) ならば case 文に渡し, shift して同じ処理を繰り返す.
前述のコマンドラインオプションの処理では "-a", "-b" といった具合に各オプションにそれぞれダッシュ(-) が付いたものだけを対象としていた. しかしながら,複数のオプションをまとめて "-ab" というかたちで指定することも考えられる. また,引数をともなうオプションの場合, 前述の方法では "-o foo" というようにオプション (-o) と引数 (foo) とをスペースで区切って指定しなければならず, "-ofoo" という具合にくっつけて書くことは許されない. こういった場合にも対処できるのが getopts である.
getopts は以下のように while と組み合わせて使われることが多い:
while getopts "ab:c" opt do case $opt in a ) echo "オプション a" ;; b ) echo "オプション b " echo "引数 $OPTARG" ;; c ) echo "オプション c" ;; esac done shift $(($OPTIND - 1)) ......
     これを順に説明する.
     
     まず,getopts の 1 つ目の引数 
     "ab:c"
     はオプションのパターンを意味している:
     
つまり,このスクリプトでは -a, -b, -c の 3 つのオプションが用意されており, -b オプションを用いる場合はその後ろに引数が必要である. (コロンが b の後ろに書かれている.) なお,オプションは -ac というようにくっつけて指定されてもよい. その場合は自動的に -a と -c とに分けて解釈される.
getopts の 2 つ目の引数 opt はパターンとマッチしたオプション(ダッシュ '-' は含まれない) が格納される変数名を表す.
これら 2 つの引数とともに getopts を while 文の条件部に書くと 全てのオプションについて順次処理が繰り返される.
また,-b オプションのように引数が指定されている場合, その引数は変数 OPTARG として参照される.
なお, 途中で shift 処理は必要無い. その代わり,最後にまとめて
shift $(($OPTIND - 1))とする. (変数 OPTIND には次に処理する引数の番号が格納されている. 括弧を二重に書いているのは算術演算式(後述)であり, これは「処理したオプションの個数」だけ shift することを意味している.)
もし,無効なオプションが指定されたときは, エラーメッセージが自動的に表示され, opt には ? が格納される. 自動的に出力されるエラーメッセージを抑制したい場合は, オプションのパターンの先頭にコロンを付け, ":ab:c" のようにする. そして,case 文の最後に
      \? ) エラー処理
      exit 1 ;;
     
     という部分を付け加えるとよい.
これまで,変数では文字列を扱ってきたが, 変数を整数型として処理したり, 参照のみ(read only)に設定することもできる. そのための組込みコマンドが declare である.
declare のオプション オプション 意味 -f 関数名しか使用しない -i 変数は整数型として処理される -r 変数は参照のみ可能にする -x 変数を環境変数として参照可能にする(export する) (オプションを - でなく + で指定することで, その機能を無効にできる.) 
(例)6.3 整数型変数と数値演算
上の例から分かるように, そのまま変数に整数を代入しても演算は行われず 変数の内容が展開されるにすぎない. しかし,declare -i を付けることで変数が整数型として処理され演算が行われる.
同様に declare -r で変数を参照のみ可能にすることができるが, これは readonly というコマンドを用いて
としてもよい.
としたうえで,
としても "10*5" が表示されるが,
とすれば "50" が表示される. (この場合,aaa, bbb には $ を付けなくても変数として処理される.)
このようにして利用できる数値演算子を以下に示す.
| 演算子 | 意味 | 
| + | 加算 | 
| >> | 右にビットシフト | 
| - | 減算 | 
| & | 論理積 | 
| * | 乗算 | 
| | | 論理和 | 
| / | 除算(切り捨て) | 
| ~ | 論理否定 | 
| % | 剰余 | 
| ! | 論理否定 | 
| << | 左にビットシフト | 
| ^ | 排他的論理和 | 
また,この数値演算式では論理型の処理もできる. これは C 言語の条件式と同じで,真ならば 1, 偽ならば 0 となる. 例えば, $(( 3 > 2 )) の値は 1 となり, $(( (3>2) && (4<=1) )) の値は 0 になる.
| 演算子 | 意味 | 
| < | より少ない | 
| == | 等しい | 
| > | より大きい | 
| != | 等しくない | 
| <= | 以下 | 
| && | 論理積 | 
| >= | 以上 | 
| || | 論理和 | 
数値の大小関係を評価する方法については既に 整数による条件式 で述べた. そこでは
のように [ と ] で囲むことで評価し, それが正常終了すれば then 部が, さもなくば else 部が実行される. これを(上述の)数値演算式を用いて表すと
のようになる. ここで,"= 1" を付けていることに注意が必要である. 3 < 2 は偽であるため $((3 < 2)) の評価値は 0 になる. しかしながら,これを終了ステータスとして処理すると, 0 は正常終了を意味するため真偽が反転してしまう. そのため "= 1" を付けて評価する必要がある.
前述したように "declare -i" を付けることで変数を整数型として定義できる. これに加えて let ステートメントを利用すれば, 数値演算式の計算結果を変数に代入することもできる. その構文は
である. let では, 式 を数値演算式として解釈するため, $(( と )) で囲む必要はない. 例えば,
とすれば aaa の値は 5 になる. (let がなければ "1+4" になる)