f
나는 다음을 기반으로 Bash에서 함수를 정의했습니다.여기 예("매개변수가 있는 옵션" 아래):
f () {
while getopts ":a:" opt; do
case $opt in
a)
echo "-a was triggered, Parameter: $OPTARG" >&2
;;
\?)
echo "Invalid option: -$OPTARG" >&2
return 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
return 1
;;
esac
done
}
그들은 스크립트를 사용하는 반면 저는 쉘에서 직접 함수를 정의합니다.
Bash를 처음 시작하고 다음 함수를 정의하면 모든 것이 잘 작동 f -a 123
합니다 -a was triggered, Parameter: 123
. 하지만 똑같은 라인을 두 번째로 실행하면,아무것도 인쇄되지 않습니다.
이 동작의 원인은 무엇입니까? Bash 3.2 및 4.3에서 발생하지만 Zsh 5.1에서는 잘 작동합니다. 이 예제는 Zsh가 아닌 Bash에 대한 것이므로 이는 놀라운 일입니다.
답변1
bash는 옵션을 얻습니다환경 변수 사용선택추적 처리를 위한 마지막 옵션 매개변수입니다. 실제로 OPTIND
동일한 쉘 세션 내에서 호출될 때마다 자동으로 재설정되지 않고 getopts
쉘이 호출될 때만 재설정됩니다. 따라서 getopts
동일한 매개변수를 사용하여 동일한 세션에서 두 번째로 호출하면 OPTIND
아무 것도 변경되지 않으며 getopts
작업을 완료했다고 생각하고 아무 작업도 수행하지 않습니다.
OPTIND
제대로 작동하도록 수동으로 재설정 할 수 있습니다 .
$ OPTIND=1
$ f -a 123
-a was triggered, Parameter: 123
아니면 함수를 스크립트에 넣고 스크립트를 여러 번 호출하면 됩니다.
zsh는 옵션을 얻습니다약간 다른. OPTIND
일반적으로 쉘 함수가 종료될 때마다 1로 재설정됩니다.
답변2
어떤 함수에서든 지역 변수를 선언하는 것은 신성한 습관입니다. $opt, $OPTARG 및 $OPTIND를 선언하면 함수를 호출할 때마다 getopts가 실행됩니다. 함수가 완료된 후 지역 변수는 삭제됩니다.
#!/bin/bash
function some_func {
declare opt
declare OPTARG
declare OPTIND
while getopts ":a:" opt; do
echo $opt is $OPTARG
done
}
답변3
OPTIND=1
함수 시작 부분에 설정 해야 합니다 f
. 기본적으로 1이지만 인수가 구문 분석됨에 따라 증가합니다. 다시 호출 하면 getopts
중단된 부분부터 계속됩니다. 두 번째 전화가 다음과 같은 경우:
f -a 123 -a 999
999를 인쇄할 때.
답변4
호출 되면 getopt
변수를 통해 처리된 옵션을 추적합니다 OPTIND
.
다음을 시도해 보십시오:
#!/bin/bash
f () {
printf "Intro OPTIND: %d\n" "$OPTIND"
while getopts ":a:b:" opt; do
printf "Current OPTIND: %d\n" "$OPTIND"
case $opt in
a)
echo "-a was triggered, Parameter: $OPTARG" >&2
;;
b)
echo "-b was triggered, Parameter: $OPTARG" >&2
;;
esac
done
printf "Exit OPTIND: %d\n" "$OPTIND"
}
echo "Run #1"
f "$@"
echo "Run #2"
f "$@"
생산하다:
./test -a foo -b bar
Run #1
Intro OPTIND: 1
Current OPTIND: 3
-a was triggered, Parameter: foo
Current OPTIND: 5
-b was triggered, Parameter: bar
Exit OPTIND: 5
Run #2
Intro OPTIND: 5
Exit OPTIND: 5
그래서 당신은 이것을 할 수 있습니다 :
OPTIND=1
함수 시작 부분에. 또는 일반적으로 상황에 따라 더 나은 방법은 다음과 같습니다.
local OPTIND
사용하지 않으면 OPTIND
함수가 구현되는 동안 while 루프가 영원히 계속됩니다. 또한 이를 사용하여 매개변수 처리를 재개할 수 있습니다. 오류가 발생한 후 또는 x 또는 y가 다른 함수를 호출하면 중단된 부분부터 다시 시작됩니다.