나는 이 bash 코드를 getopts와 결합했고, getopts를 올바르게 이해했다면 OPTIND에는 다음 명령줄 옵션의 인덱스가 포함되어 있으며 쉘 스크립트에 제공된 모든 명령줄 옵션은 변수 $1, $2, $3 등에 표시됩니다. 그렇다면 제 말을 정정해 주십시오. 제가 틀렸지만 기본적으로 함수의 지역 변수와 동일한 개념입니다.
그래서 이것에 따르면 옵션이 나에게 어떤 결과도 제공 [-a somevalue ]
하지 않는 이유는 무엇입니까? [-b somevalue ]
내가 뭘 잘못했나요?
OPT_A=A
OPT_B=B
while getopts :a:b FLAG; do
case $FLAG in
a)
OPT_A=$OPTARG
;;
b)
OPT_B=$OPTARG
;;
esac
done
shift $((OPTIND-1))
while [ $# -ne 0 ]; do
if [[ -z $OPT_A ]]; then
if [ `echo $1 | grep -o '\.' | wc -l` -ne 3 ]; then
echo "Parameter '$1' does not look like an IP Address (does not contain 3 dots).";
exit 1;
elif [ `echo $1 | tr '.' ' ' | wc -w` -ne 4 ]; then
echo "Parameter '$1' does not look like an IP Address (does not contain 4 octets).";
exit 1;
else
for OCTET in `echo $1 | tr '.' ' '`; do
if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' is not numeric).";
exit 1;
elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' in not in range 0-255).";
exit 1;
fi
done
fi
fi
if [[ -z $OPT_B ]]; then
if [[ "$2" =~ ^[0-9]+$ ]] && [ "$2" -ge 1 -a "$2" -le 10000 ]; then
echo "chosen variable: $2";
exit 1;
else echo "variable $2 is not in range '1 - 10000'";
exit 1;
fi
fi
done
exit 0
답변1
이는 모든 논리가 그 중 하나가 $OPT_[AB]
비어 있어야 하기 때문입니다. 하지만 매개 변수를 전달하지 않더라도 -[ab] $OPTARG
계속 사용할 수 있습니다 OPT_[AB]=[AB]
. 따라서 논리 체인은 루트를 통과하지 못합니다.
if [[ -z $OPT_A ]]; then...
...성명.
음 .. 아니야모두당신의 논리는 이것에 달려 있습니다. 당신은 또한 다음을 하고 있습니다:
shift $((OPTIND-1))
while [ $# -ne 0 ]...
따라서 통과하면 3 으로 설정 script -a arg
됩니다 . 그래서 당신은 것입니다getopts
$OPT_A
arg
$OPTIND
shift 2
(모든 게시물)그러면 테스트가 즉시 실패합니다 while
. 따라서 을 case
설정하면 $OPT_A
다음에 일어날 일은 입니다 exit 0
. 그래서 $OPT_A
사용 가능한지 확인하지 않은 것 같습니다 .
그럼에도 불구하고 대부분의 논리는 테스트 실패를 위해 설계되었으므로 중요하지 않습니다. 그러나 스크립트는오직 exit
에스. var를 만들었지 $OPT_A
만 아무 작업도 수행하지 않을 수 있습니다. 스크립트 후에는 이 값을 사용할 수 없습니다 exit
. 미리 설정된 IPC가 없지만 여기에는 그런 것이 없습니다. 스크립트는 서브쉘에서 호출되며, 상위 쉘로 돌아가면 설정한 값은 손실됩니다.
더 중요한 것은 :a:b
optstring $OPTARG
이 -b
. optstring의 선행 콜론은 자동 작동을 나타냅니다. stderr
옵션이나 해당 인수에 문제가 있으면 기록되지 않습니다. 하지만 콜론뒤따라옵션 문자는 옵션에 인수가 있어야 함을 나타냅니다. 좋다:
while getopts :a:b: FLAG
...인수가 필요한 두 가지 옵션을 나타냅니다. 그러나 이는 까다로울 수 있습니다. 인수를 허용해야 한다고 표시한 후 getopts
인수가 없는 것으로 확인되면 오류로 표시되기 때문입니다.
sh -c 'getopts :a:b: opt -a; echo "$opt $OPTARG"'
...인쇄...
: a
이 경우 옵션은 결국 가 됩니다 $OPTARG
. 우리가 그것에 대해 덜 침묵한다면 그것은 더 명확해질 것입니다::
$opt
:
sh -c 'getopts a:b: opt -a; echo "$opt $OPTARG"'
No arg for -a option
:
따라서 콜론을 확인해야 하며 ?
이는 일반적으로 간단한 내용을 인쇄하기 위해 경로를 재설정하는 또 다른 유형의 오류입니다 --help
.
$OPT_[AB]
개인적으로 저는 처음부터 그것들이 모두 비어 있는지 확인하고 몇 가지 논리를 수행하여 올바르게 설정한 다음 테스트 루프를 완료한 후 마지막 테스트를 비어 있도록 설정합니다. 그것들이 전혀 가치가 없다면 그것은 내가 다루지 않는 어떤 이유에서임에 틀림없으며 어쨌든 그것은 버그입니다. 이것이 테스트 루프를 수행하는 방법의 시작입니다...
param_err(){
set '' "$@"
: "${1:?Parameter '$OPTARG' does not look like an IP Address $2}"
}
test_oct(){
oIFS=$IFS; unset "${IFS+o}oIFS"; IFS=.
for oct in $1; do [ $oct -lt 256 ] ||
param_err "('$oct' too large)"
done; unset IFS oct
: "${oIFS+${IFS=$oIFS}}"
}
a_param()
case ${1##*.*.*.*.*} in (a) OPT_A=A;; #some default - no arg provided
(.*|*..*|*.) param_err '(empty octet)';;
(*[!.0-9]*) param_err '(octet is not positive integer)';;
(*.*.*.*) test_oct "$1"; OPT_A=$1;;
(*?*) param_err '(too few octets)';;
(*) param_err ${1:+"(too many octets)"} '(null param)';;
esac
unset OPT_A OPT_B
while getopts :a:b:c:d: opt
do case ${opt#:}$OPTARG in
a*) a_param "$OPTARG";;
b*) b_param "$OPTARG";; #tests as needed similar to a_param()
?*) help;; #param_err should call this too, but it just exits
esac
done
답변2
상단에 셔뱅라인이 없으므로 사용중인 쉘( sh
, dash
)이 이를 지원하지 않을 수 있습니다 [[
. 다음 명령을 사용하여 스크립트를 시작해야 합니다.
#!/bin/bash
또는 다른 위치 bash
(만약 이것이 시스템의 bash 경로가 아닌 경우 type bash
).
답변3
이것을 변경해보세요: while getopts :a:b FLAG do;
이를 위해: while getopts :a:b: FLAG;