bashケース&&追加OPTARG

bashケース&&追加OPTARG

昨夜は興味深いシナリオに直面し、これまで私の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-rgetopt

GNUルールは、次から始まるパラメータです。- コマンドラインのどこでも引数が前にない限りオプションですが、--オプション引数は計算されません。 GNUルールによれば、mwctl -D -a weblogic -c start admin -e trn -rオプション-D、引数付きオプション、引数付きオプション、オプションではない引数、引数付きオプション-a、オプションがあります。weblogic-cstartadmin-etrn-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改良されたバージョンがあります。

関連情報