getopts組み込みコマンドは、シェルスクリプトの引数リストをパースした際に見つけた値($1や$2など)を2つめの引数で指定された変数に設定する。「-」で始まる引数はオプション引数とみなされ、「-」を除いた文字の部分だけが指定された変数(上記の例では$OPTION)に代入される。その後getoptsは真(0)を返すので、whileループがオプションを処理して、その後、引数がなくなるまで(またはユーザがオプションの終了を明示的に示すために入力した「--」を見つけるまで)getoptsが繰り返し呼び出されてオプションのパースが続けられる。最後にgetoptsが偽(非0)を返してwhileループが終了する。
ループの中では、$OPTION変数に対してcase文を用いて、処理すべきオプション文字がパースによって見つかった場合に、フラグを設定したりオプションが指定された場合に行なうべき動作を行なったりしている。一方、引数を取るオプションの場合、その引数はシェル変数「$OPTARG」に設定される(なお$OPTARGは既定の名前であり、ここで変数として利用している$OPTIONとは関係ない)。ただし$OPTARG変数の値は、while文でループが繰り返し実行され、getoptsが呼び出される度にリセットされるため、別の変数に代入して保存しておく必要がある。
例の中のcase文の3つめのパターンは「?」で、任意の一文字にマッチするシェルのパターンだ。getoptsは、定義されたオプション群(ここでは'ab:')以外のオプションを見付けた場合、変数(ここでは$OPTION)の中にリテラルの「?」を代入する。したがってcase文を \?) または '?') として「?」そのものにマッチさせることもできるが、ここでのcase文のデフォルトとしては、任意の一文字にマッチするパターンとして「?」を使っておけばリテラルの「?」も含めた任意の一文字にマッチするので便利だ。
使い方のメッセージを表示する部分では、マニュアルページに掲載されているスクリプト例に2点変更を加えた。1つめの変更点としては、起動時に使用される可能性のある余分なパス名をすべてなくしたスクリプト名を表示するために$(basename $0)を使用するようにした。2つめの変更点としては、使い方のメッセージを標準エラー出力(>&2)に出力するようにした。未知のオプションや引数不足の場合のgetoptsのエラーメッセージはすべて必ず標準エラー出力に出力されるので、使い方のメッセージもそれに合わせた。
whileループが終了すると、次に以下のような行が実行される。
shift $(($OPTIND - 1))
上記の行ではshift文を使用して、$1や$2のようなシェルスクリプトの位置パラメータを、与えられた数だけ前に移動している(つまり前方にあるパラメータを捨てている)。$OPTIND変数は、getoptsがパース時の位置を覚えておくために使用する、引数のインデックスだ。したがってこのshift文を実行することにより、パースの完了後、処理が終わったオプションをすべて捨てていることになる。例として以下のようなコマンドラインを考えてみよう。
myscript -a -b alt plow harvest reap
この場合、オプションのパースを終えた時点で$OPTINDは4になっている。($OPTIND-1)によりシフトが3回実行されるので、引数のうちオプション引数だけが捨てられることになり、例えば「echo $*」を実行してみると次のような結果になる。
plow harvest reap
したがって残りの(オプションではない)引数を(おそらくforループの中などで)利用しやすい状態になる。上記のスクリプト例では、最終行のprintfで残りの引数をすべて表示した。
