シェルスクリプト (sh, bash) での getopts の雛型

シェルスクリプトで引数の処理をしたい場合は、getopts が便利ですね。
使い方を忘れてしまいがちで、かつ、決まった形式で使うことが多いので、メモついでに雛型を作っておきます。

雛型

#!/bin/sh
#
# 20111207
# getopts test
#
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/sbin:/usr/sbin  
export PATH


#
# usage
#
_usage() {      #(*1)  
  echo "usage:"
  echo "${0} -a -b HOGE [-c] [-d FOO] [BAR]"
  exit 1
}


#
# getopts
#
while getopts :ab:cd: OPT; do      #(*2)  
  case ${OPT} in
    a) ENABLE_a="t";;
    b) ENABLE_b="t"; VALUE_b=${OPTARG};;
    c) ENABLE_c="t";;
    d) ENABLE_d="t"; VALUE_d=${OPTARG};;

    :|\?) _usage;;      #(*3)
  esac
done

shift `expr ${OPTIND} - 1`      #(*4)


#
# check
#
[ "${ENABLE_a}" != "t" ] && usage      #(*5)
[ "${ENABLE_b}" != "t" ] && usage


###### 以降は処理 ######

解説

*1
usage の表示。
オプションに不備があった場合などに実行される function。
最後に exit 1 があるので、ここでシェルスクリプトが終わる。

*2
getopts の引数は、先頭にコロンがあると "静かなエラー報告" を行うようになる。
以下のようなエラーが出なくなる。

./test.sh: option requires an argument -- b
./test.sh: illegal option -- x

*3
無効なオプションが指定された場合、${OPT}? が入る。
また、必要なオプション引数がない場合、${OPT}: が入る。
その場合は _usage を実行する。

*4
オプションをシフトする。
BAR の値が ${1} で取れるようになる。

*5
オプションのチェックをする。不備がある場合は _usage を実行する。
ここでは、-a, -b を必須オプションにしたい場合の例を示している。

以下のように、工夫して書けば結構凝ったことができるハズ。

# -a, -b どちらかが必須
[ "${ENABLE_a}${ENABLE_b}" != "t" ] && usage

# -c があるときは -d が必須
if [ "${ENABLE_c}" = "t" ]; then  
  [ "${ENABLE_d}" != "t" ] && usage
fi