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, -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향상된 버전이 있는 것입니다.

관련 정보