shell scriptでlong optionを処理する
- 2016.10.16
- 未分類
仕事でシェルスクリプトを時々書く。
オプション処理にはgetoptsを使っている。
オプションの種類が増えてくると
意味が分かりやすいロングオプションが使いたいくなるが
getoptsではショートオプションしか使えないらしい。
こちらの記事や
bash によるオプション解析
こちらの記事が
bashでロングオプションとショートオプションの両方に対応する
とても参考になり、やり方を考えてみた。
環境依存なgetoptはなるべく使いたくないし
自作せずに既存の方法をなるべく使って実現したくなる。
こんな感じかなぁ。。
ポイントはロングオプションが指定されたらoptとOPTARGを書き換えて
それ以降の処理をショート/ロングオプション共通にすること。
#!/bin/bash check_arg_exit(){ # オプションの引数がなかったら終了 if [ -z "$OPTARG" ]; then echo "${0##*/}: option needs arg -- $opt" exit 1 fi } while getopts "hf:-:" opt; do if [ $opt = "-" ]; then opt=`echo ${OPTARG} | awk -F'=' '{print $1}'` OPTARG=`echo ${OPTARG} | awk -F'=' '{print $2}'` fi case "$opt" in h | help) echo "help" exit 0 ;; f | file) check_arg_exit echo "target file name is ${OPTARG}." ;; ? ) exit 1 ;; # ここはgetoptsのエラー出力に任せる * ) echo "invalid option -- $opt" exit 1 ;; # 未定義のlong optionのエラーはここで出力 esac done shift $((OPTIND - 1)) echo "main process" exit 0
必須のオプション引数が指定されなかった時に
エラーを表示する方法がないので自前で「check_arg_exit」を定義しておき
必要なcase節に書いておく。
全部自前の「check_arg_exit」に統一しようと思って
getoptsのオプション指定の先頭にコロンを足して
エラー表示をしないようにしたのだけど
while getopts ":hf:-:" opt; do
これだとfオプションが引数無しで使われたときにcase文が?節に落ちる。
未定義のショートオプションを使った場合も?節に落ちるので
エラー表示を「オプション引数がない」にすればよいのか
「未定義のオプション」にすればいいのかわからないので諦めて
ショートオプションのエラー表示は全部getoptsに任せることにする。
(2016/10/16訂正)
man bashを読むとgetoptsは「silent」(オプション指定の先頭がコロン)なら
必須引数無は「:」、未定義オプションは「?」がoptにセットされるので区別可能。
「not silent」ならいずれも「?」がoptにセットされるらしい。
でもこのときoptが「:」や「?」になっていて
元のオプション文字はOPTARGに入っているので
自前のエラー処理と共通化できない。
ので、結局ショートオプションのエラー表示はgetoptsにお任せ。
未定義のロングオプションが指定されたら
エラー表示したいのでcase文の最後のアスタリスク節は必要。
その前の?節が無いと、未定義のショートオプションを指定した時に
getoptsからエラー表示が出てアスタリスク節でも自前のエラー表示も出てしまうので必要。
$ ./longopt.sh -a ./longopt.sh: 不正なオプションです -- a invalid option -- ?
これでやりたいことは全部できてそう。
・ロングオプションを処理できる
・ロングオプションに引数指定できる
・未定義オプションでエラーを表示
・必須のオプション引数が無いときにエラー表示
あと出来てないのはこれぐらいだろうか。
私の用途ではこれらの要件は不要なので、もう満足です。
・通常引数の後にオプション指定
・引数があってもなくてもよいロングオプション
主な実行結果。
$ longopt.sh main process $ longopt.sh -h help $ longopt.sh --help help $ longopt.sh -f /home/UserName/mysh/longopt.sh: オプションには引数が必要です -- f $ longopt.sh -ffilename target file name is filename. main process $ longopt.sh -f filename target file name is filename. main process $ longopt.sh --file longopt.sh: option needs arg -- file $ longopt.sh --file=filename target file name is filename. main process $ longopt.sh -a /home/UserName/mysh/longopt.sh: 不正なオプションです -- a $ longopt.sh --hoge invalid option -- hoge
-
前の記事
cutコマンドでデリミタ(区切り文字)の連続を1つの区切りにできない 2016.10.10
-
次の記事
bashのリダイレクトとパイプとファイルディスクリプタ 2016.11.02