解決する問題
- 参考: bash によるオプション解析
-
getopts
ではロングオプションが解析できない -
getopts
のオプション指定方法が覚えられない - スクリプトの半分くらいがオプション解析になる
- だいたいボイラープレートっぽい
- ヘルプとオプション解析を同時にメンテするのが辛い
解決策
ヘルプ用のテキストと引数を解析して、環境変数に設定するスクリプト
を作りました。ご利用ください。ライセンスはMITです。
インストール
longoption.sh を適当な名前でPATHの通ったところにおいて、実行権限をつけてください。
基本的な使い方
# まず、ヘルプを用意します
HELP="
--opt1 OPTION1 値付きのオプション1です
--opt2 OPTION2 値付きのオプション2です
--flag 値なしのオプション(フラグ)です
"
# ヘルプを longoption.sh のひとつ目の引数として渡し、残りも渡します。
# 出力結果を eval すると(ダブルクオートが大変なことになっているけど大事)
eval "$(longoption.sh "$HELP" "$@")"
# 結果を環境変数で受け取っています
echo opt1=$OPTION1
echo opt2=$OPTION2
echo flag=$FLAG
# ヘルプは LONGOPTION__HELP_TEXT に入っていますので、必要ならそれを表示します
if [ -z "$OPTION1" ];then
echo "$LONGOPTION__HELP_TEXT" #
exit
fi
# オプションとして有効でなかった引数は LONGOPTION__OTHER_ARGS に入っているので、それを利用してエラーを出したり、さらなる解析をしたりできます
if [ ${#LONGOPTION__OTHER_ARGS[@]} != 0 ];then
echo "未知の引数が指定されています ${LONGOPTION__OTHER_ARGS[@]}"
echo "$LONGOPTION__HELP_TEXT"
exit -1
fi
こんな感じです。大抵の場合はこれで事足りるのではないかと思います。aws cli
作りたい時とか。
LONGOPTION__OTHER_ARGS に解析できなかった引数が入っているので、それを再度解析して、短いオプションや引数の解析などを行ってください。
動作的には、ヘルプ文の中の /^\s*--([a-z][-a-z0-9]*)\s*([A-Z][_A-Z0-9]*)/
を解析して、 \2
があれば値付きオプション、なければフラグとして扱います。フラグの場合はフラグ名を tr [-a-z] [_A-Z]
した環境変数に 0 か 1 で値を入れます。
フラグは --no-flag
のように反転フラグ宣言することができます。この場合、環境変数 FLAG
に 0 が入ります。(通常フラグはデフォルトが 0 で指定されれば 1 だが、反転フラグ宣言された場合、デフォルトは 1 で、指定されれば 0 です。値付きオプションの場合、デフォルトは空文字です)
ヘルプ文中に幾つかプラグマ指定することができ、ヘルプ文中にパースを誤作動させそうな文書を含みたかったり、隠しオプションを指定したい場合などに利用してください。
-
LONGOPTION:
この文字列で始まった場合、その行は LONGOPTION__HELP_TEXT に含まれない(オプションの指定はできる) -
LONGOPTION:STOP_PARSE
この文字列の行以降は、オプション指定が無視される( LONGOPTION__HELP_TEXT には含まれる) -
LONGOPTION:START_PARSE
この文字列の行は LONGOPTION:STOP_PARSE の効果を解除する -
LONGOPTION:STOP_HELP
この文字列の行以降は LONGOPTION__HELP_TEXT に含まれなくなる(オプションの指定がされていれば有効) -
LONGOPTION:START_HELP
この文字列の行は LONGOPTION:STOP_HELP の効果を解除する
環境変数による動作
環境変数 LONGOPTION
に引数をしてすることで、いくつか動作を変更できます。
-
--prefix PREFIX
を指定することで、オプション解析結果を入れる環境変数名に接頭語をつけることができます。例えばLONGOPTION='--prefix ARGS_'
のようにすると--hoge HOGE
の結果はARGS_HOGE
に入ります。 -
--import
を指定することで、オプション値のデフォルト値を環境変数から読み込みます。これが指定されない場合、デフォルト値は、値付きオプションの場合は空白、フラグの場合は0(反転フラグの場合は1)です。未指定か空白か、などの判定はできません。 -
--stop STOP
を指定することで、オプションの解析を停止する文字列を指定することができます。例えばLONGOPTION='--stop --'
の用に指定すると、--hoge HOGE -- --huge HUGE
という引数があっても、--huge HUGE
の部分は解析されません。
テストとサポート
Mac osx の bash3、 git for windwos の bash4、travis-ci の bash4 などで動くことをテストしています。
今後
短いオプションの解析はいろいろパターンがあり過ぎてちょっと難しい・・ -la
みたいな連結した指定方法を許すかとか、ヘルプの書式とか反転フラグの指定方法( +x
?)とか
インストール方法を考える(いい案募集・・)
英語を何とかする