bash スクリプトでオプション解析を行う場合の悩み
bash でスクリプトでオプション解析を行う時に、getopt(GNU/Linux, BSD) とgetopts(bash ビルトイン)を利用することができますが、以下のような悩みがあります。
-
getopt
-
GNU/Linux 版とBSD 版で挙動が違う
-
GNU/Linux 版ではロングオプションが利用できるがBSD 版ではできない
-
GNU/Linux 版では引数(arg)のあとにオプションを置いても引数とオプションを分けて解析できるがBSD 版ではできない
-
getopts
-
bash であれば、あらゆるOS 上で利用できる
-
ロングオプションは利用できない
-
引数のあとにオプションを置いても引数とオプションを分けて解析できない
上記の内容を考慮して、bash で少し複雑なオプション解析を必要とするスクリプトを組む場合にはgetopt(GNU/Linux) を使用したいのですがそれを使用した場合、Mac 等のLinux 環境外では利用できず不便なものとなります。
であればbash 環境下であればあらゆるOS 上で使用できるgetopts を使用したいのですが、それではロングオプションへの対応や引数のあとにオプションを置いた場合に解析できない問題がつきまとってくることになります。
そこで、上記の問題を解決するためにbash 環境であれば共通的に利用できるgetopt(GNU/Linux) があればこの問題を解決できるのではないか!
ということでbash ビルトインとして、bash 環境であれば共通で使えるgetopts を使ってgetopt(GNU/Linux) を実現できるユーテリティを作成しました!という記事です。
リポジトリ
※Bash 3 系では正しく動きません
使い方
リポジトリのgetoptses.sh をロードしてgetoptses コマンド(getopt にses がついている)をgetopt(GNU/Linux) と同じように使用すれば良いだけです。
なお、getopt にはオプションが幾つかありますが、getoptses ではよく使われる-o, --options
と-l, --long
オプションのみを実装しています。
$ git clone https://github.com/TsutomuNakamura/getoptses.git
$ cp getoptses/getoptses.sh /path/to/getoptses/
$ . /path/to/getoptses/getoptses.sh
もしくは直接getoptses.sh をロードすることもできます。
$ . <(curl -Sso- https://raw.githubusercontent.com/TsutomuNakamura/getoptses/master/getoptses.sh)
オプション解析のサンプルスクリプトは以下のようになります。
#!/bin/bash
function main() {
. /path/to/getoptses/getoptses.sh
local options
options=$(getoptses -o "ab:" --longoptions "long-a,long-b:,lonb-c" -- "$@")
if [[ "$?" -ne 0 ]]; then
echo "Invalid option were specified" >&2
return 1
fi
eval set -- "$options"
while true; do
case "$1" in
-a | --long-a )
echo "-a, --long-a"
shift
;;
-b | --long-b )
echo "-b, --long-b: $2"
shift 2
;;
--long-c )
echo "--long-c"
shift
;;
-- )
shift
break
;;
* )
echo "Internal error has occured" >&2
return 1
;;
esac
done
echo "args: $@"
return 0
}
main "$@" || exit $?
参考
-
bash によるオプション解析
-
Using getopts in bash shell script to get long and short command line options