bash と getopt の連携(2018年バージョン).

bash で getopt を使う雛形.

エラー処理をちゃんと書いたバージョンです.実行時のエラー,実装上のバグ,どちらも正しく検出&対処できます.

#!/bin/bash

usage()
{
    cat<<EOF
usage: 
        $0 [option*] [argument*]

  -a 
  -v, --value=VALUE 
  -c
EOF
    exit 1
}

opts=`getopt --name "$0"  --options hav:c --long help,value:  "$@"` || usage
eval set -- "$opts"
unset opts 

while [ -- != "$1" ]; do
    case "$1" in
	-h | --help)
	    usage 
	    ;;
	-a)
	    a=1
	    ;;
	-v | --value)
            shift
	    v="$1" 
	    ;;
	-c)
	    c=1
	    ;;
         *)
             # 実装のバグ検出時の処理をここに書く

             # タイプミスや実装漏れにより
             # getopt の引数で登録したオプションと
             # case文の pattern部分に不一致が出てくると
             # この部分に処理が飛んでくる
             echo "internal error"
             ;;
    esac
    shift 
done

## "--" を取り除く
shift


## オプションの値を表示
echo "a:=$a  value:=$v  c:=$c"

## 残りのコマンドライン引数を表示
while [ -n "$1" ]; do
    echo $1
    shift
done

実行例

$ ./fuga.sh  aaa -a  bbb
a:=1  value:=  c:=
aaa
bbb

なお上記の雛形は bashのビルトインの getopts ではなく, GNU版の /usr/bin/getopt を使っています.getopts と /usr/bin/getopt は一長一短で甲乙つけがたい面もありますが

  • long option に対応している
  • オプションの順序に制約がない

という2点で 私は /usr/bin/getopt の方が便利だと考えています.