어젯밤에 흥미로운 시나리오에 직면했고 지금까지 내 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
향상된 버전이 있는 것입니다.