Lから始まるLinux

3章15話
引数処理
3章16話 オプション処理
もくじ
3章17話
readonlyコマンド
オプション処理
若木 しげる
悩みながら シェルスクリプトを 書いているみたいだね?
若木 みどり
うん オプションを扱えるように できないかと思っているんだけど これが難しくて…
若木 しげる
引数を扱えるなら オプションも扱いたいと 考えるのはもっともだよね 実はオプションを楽に解釈する 仕組みが用意されているんだ!
若木 みどり(驚き)
えっ! 教えて欲しい!
オプション解析スクリプト
若木 しげる
getopts オプション解析コマンドだよ
若木 みどり(驚き)
専用のコマンドがあるんだね!
若木 しげる
getopts 色々な要素と組み合わせて 動く前提のコマンドなんだ 少し複雑なので 一緒にスクリプトを 読みながら理解しよう
若木 しげる
オプションを解析する check-opts スクリプトを 作成しよう!
vim check-opts
若木 みどり
うん!
若木 しげる
そこに以下の内容を書いてね
#!/bin/bash

# 初期状態
OPT_A=off
OPT_B=off
OPT_C=off
OPT_C_VALUE=

# オプションを処理
while getopts "abc:" OPT
do
  case "$OPT" in
    a) # a オプション
      OPT_A=on
      ;;
    b) # b オプション
      OPT_B=on
      ;;
    c) # c オプション(引数付き)
      OPT_C=on
      OPT_C_VALUE="$OPTARG"
      ;;
    *) # 不正なオプション
      echo "エラー: 無効なオプション $OPT が指定されました" >&2
      exit 1
      ;;
  esac
done

# オプション処理結果を表示
echo "オプションa: $OPT_A"
echo "オプションb: $OPT_B"
echo "オプションc: $OPT_C"
[ "$OPT_C" == "on" ] && echo "オプションc値: $OPT_C_VALUE"

# 引数を処理
shift $((OPTIND - 1))
for ARG in "$@"
do
  echo "引数: $ARG"
done
echo "引数の個数: $#"
若木 みどり
ちょっと長かったけど書けたよ!
若木 しげる
そうしたら実行権限を与えて実行できるようにしよう
chmod a+x check-opts
若木 みどり
これで実行する準備はできたね!
若木 みどり
名前のとおりオプションを確認するんだよね?何を指定すればよいかな?
若木 しげる
このスクリプトは-a, -b, -c オプションを認識するよ-c は、head -n 1 のように「オプション引数」を受け取るんだオプションの指定が終わった後の要素は引数と判断してくれるよ書式は以下のような感じだね
./check-opts [-a] [-b] [-c 値] [引数]...
若木 みどり(驚き)
へぇ…いくつか試してみるね!
./check-opts -a
オプションa: on
オプションb: off
オプションc: off
引数の個数: 0
./check-opts -ab
オプションa: on
オプションb: on
オプションc: off
引数の個数: 0
./check-opts -c X aaa bbb ccc
オプションa: off
オプションb: off
オプションc: on
オプションc値: X
引数: aaa
引数: bbb
引数: ccc
引数の個数: 3
若木 みどり(驚き)
すごい!オプションと引数をちゃんと解析できてる!ショートオプションの同時指定もバッチリ!
getopts コマンド
若木 しげる
getopts以下の書式で使うよ
getopts オプション文字列 変数名
若木 しげる
オプション文字列にはショートオプションとして認識する文字を並べるんだ
若木 しげる
オプション文字の後に: を指定するとそのオプションは引数を取ると解釈されるんだ
若木 みどり
ここの指定は abc: だよね
getopts "abc:" OPT
若木 みどり
だから -a, -b, -c オプションを認識して-c オプションはオプション引数を取るんだね
若木 しげる
続く変数名の変数に解析したオプション文字が代入されるよこれをcase文で処理を分けてあげればオプションごとに処理を書けるというわけなんだ
若木 みどり
オプションが指定されていれば対応する変数の値をoff から on にしているんだね
若木 しげる
オプション引数が指定されていた場合OPTARG 変数にその値が代入されるよこの変数を参照することでどんな値が指定されたかがわかるんだ
若木 しげる
getoptsオプション解析を続けられるなら成功そうでないなら失敗を返すんだだから getoptswhile文と一緒に使われるよ
若木 みどり
while文の後にshift を実行しているね?
若木 しげる
OPTIND 変数には getopts現在解析している引数の番号が入っているんだ1 から始まり次の要素の解析に移る時に値が 1 増加するよ
若木 しげる
だからwhile 文を終えたときの OPTIND 変数にはオプション解析が終わったときの引数の番号つまり「最後のオプション + 1」番目の引数の番号が入っていることになるよ
若木 みどり
そこで shift $((OPTIND - 1)) を実行すると解析済みのオプションを全て捨てて残りは全て引数というというわけなんだね…
まとめ
若木 みどり
今回は getopts でオプションと引数を解析できることを学んだよ!ちょっと書き方が独特で覚えることが多いね…
若木 しげる
getopts は今回書いたような決まりきった使い方をするんだ最初はこの check-opts スクリプトを雛形にして自分のスクリプト用に内容を書き換えてあげるといいよ!