昨夜は興味深いシナリオに直面し、これまで私のGoogle fooは解決策を見つけることができませんでした。複数のパラメータをサポートするスクリプトがあります。ユーザー(およびそのユーザー)はオプションの引数を指定せず、結果は予想外です。
パスワード:
while getopts "a:c:d:De:rs:" arg
do
case ${arg} in
a) app=${OPTARG} ;;
c) cmd=${OPTARG} ;;
d) domain=${OPTARG} ;;
D) Debug=1 ;;
e) env=${OPTARG} ;;
r) Doit=1 ;;
s) subapp=${OPTARG} ;;
*) echo "You are DISCREPANT!!";;
# *) usage "Invalid argument ${arg}::${OPTARG}" ;;
esac
done
if [ ${Debug} -gt 0 ]
then
echo "Env: ${env}"
echo "App: ${app}"
echo "Subapp: ${subapp}"
echo "Cmd: ${cmd}"
echo "Doit: ${Doit}"
echo "Debug: ${Debug}"
exit 1
fi
すべてのパラメータを正しく指定すると、次の結果が得られます。
$ ./mwctl -a weblogic -c start -s admin -e trn -r -D
Env: trn
App: weblogic
Subapp: admin
Cmd: start
Doit: 1
Debug: 1
「-s」を忘れた場合、次のような結果になります。
$ ./mwctl -D -a weblogic -c start admin -e trn -r
Env:
App: weblogic
Subapp:
Cmd: start
Doit: 0
Debug: 1
他のパラメータをスキップするオプションを使用すると、同様の結果が得られます。 「ケース」は、OPTのないOPTARGに会うと精神を失うようです...
私はこれをキャッチする方法について少し失った。
答え1
従来のUnixルールは、コマンドラインにオプション(オプションパラメータを含む)があることです。それからコマンドのオプションではない引数です。のmwctl -D -a weblogic -c start admin -e trn -r
オプションは-D
(パラメータなし)、-a
(パラメータ:weblogic
)、-c
(パラメータstart
:)です。次の言葉はadmin
、これはオプションではなくてオプションが終わりましたね。したがって、オプションではないパラメーターは、、admin
および-e
です。組み込み関数はこの規則を実装します。trn
-r
getopt
GNUルールは、次から始まるパラメータです。-
コマンドラインのどこでも引数が前にない限りオプションですが、--
オプション引数は計算されません。 GNUルールによれば、mwctl -D -a weblogic -c start admin -e trn -r
オプション-D
、引数付きオプション、引数付きオプション、オプションではない引数、引数付きオプション-a
、オプションがあります。weblogic
-c
start
admin
-e
trn
-r
case
「精神を失うこと」ではなく、あなたの問題はそれとは何の関係もありませんcase
。コードにオプション以外のパラメータ抽出がありません。
case $arg in …
esac
shift $((OPTIND - 1))
echo "There are $# non-option arguments, the first is $1"
コマンドがオプションではなく引数をサポートしていない場合は、それを明示的に指定する必要があります。
…
shift $((OPTIND - 1))
if [ $# -ne 0 ]; then
echo >&2 "Extraneous argument: $1"
exit 3
fi
答え2
getopt
代わりに、以下を使用してくださいgetopts
。
#!/usr/bin/env bash
OPT=$(getopt \
--options a:c:d:De:rs: \
--name "$0" \
-- "$@"
)
if [ $? -ne 0 ]; then
echo You are doing it wrong!
exit 1
fi
eval set -- "${OPT}"
while true; do
case "$1" in
-a) app=${2}; shift 2;;
-c) cmd=${2}; shift 2;;
-d) domain=${2}; shift 2;;
-D) Debug=1; shift;;
-e) env=${2}; shift 2;;
-r) Doit=1; shift;;
-s) subapp=${2}; shift 2;;
--) break;;
esac
done
echo "Env: ${env}"
echo "App: ${app}"
echo "Subapp: ${subapp}"
echo "Cmd: ${cmd}"
echo "Doit: ${Doit}"
echo "Debug: ${Debug}"
$ ./mwctl -a weblogic -c start -s admin -e trn -r -D
> Env: trn
> App: weblogic
> Subapp: admin
> Cmd: start
> Doit: 1
> Debug: 1
$ ./mwctl -D -a weblogic -c start admin -e trn -r
> Env: trn
> App: weblogic
> Subapp:
> Cmd: start
> Doit: 1
> Debug: 1
Googleを検索すると、多くの人が文句を言うことがgetopts
わかりgetopt
ますgetopt
。私が知っている限り、これは常にgetopt
バグの多くの古いバージョンについてです。私の経験にgetopt
よるとgetopts
。
拡張バージョンがあるかどうかを確認するには、getopt
次を実行できます。
getopt -T
echo $?
出力があれば、4
改良されたバージョンがあります。