한 스크립트에서 다른 스크립트로 모든 매개변수를 전달하려고 합니다. 그러나 다른 스크립트를 가져올 때 문제가 발생합니다. 모든 매개변수가 올바르게 전달되지 않습니다.
첫 번째.sh:
#!/usr/bin/bash
while getopts a option
do
case "${option}"
in
a) echo 'OptionA:somevalue';;
esac
done
# This way works
./second.sh "$@"
# Does not work when source command is used
#source ./second.sh "$@"
두 번째.sh:
#!/usr/bin/bash
while getopts b:c option
do
case "${option}"
in
b) echo 'OptionB:'"${OPTARG}";;
c) echo 'OptionC:somevalue';;
esac
done
산출:
$ ./test.sh -a -b foo -c
OptionA:somevalue
./first.sh: illegal option -- b
./second.sh: illegal option -- a
OptionB:foo
OptionC:somevalue
예상 출력:
$ ./test.sh -a -b foo -c
OptionA:somevalue
OptionB:foo
OptionC:somevalue
달성하려는 목표는 무엇입니까?
second.sh
매개변수를 올바르게 전달하고 , 제거하고 illegal option
, 다른 쉘과 호환되도록 하려면 source 명령을 사용하십시오 .
편집 : 더 명확한 예를 들어 질문을 다시 업데이트했습니다.
답변1
while getopts
일반적인 상황에서 루프가 어떻게 작동하는지 고려하십시오 . getopts
명령줄 인수 자체(위치 인수)를 수정하지 않더라도 루프가 반복될 때마다 호출되며 다음에 찾을 인수 목록의 위치를 알아야 합니다. 호출에서 명시적으로 전달되지 않는 "숨겨진" 상태를 유지하여 이를 수행해야 합니다.
이것은배쉬 참조 매뉴얼:
호출할 때마다
getopts
다음 옵션을 쉘 변수에 넣습니다.이름, 초기화이름존재하지 않는 경우 변수로 처리될 다음 매개변수의 인덱스입니다OPTIND
.OPTIND
쉘 또는 쉘 스크립트가 호출될 때마다 1로 초기화됩니다. 옵션에 인수가 필요한 경우 getopts는 인수를 변수에 넣습니다OPTARG
.쉘은OPTIND
자동으로 재설정되지 않습니다.getopts
새로운 매개변수 세트를 사용하려면 동일한 쉘 호출 내에서 호출 간에 수동으로 재설정해야 합니다.
스크립트를 얻으면 OPTIND
.
설명서에 나와 있듯이 OPTIND=1
새 getopts
주기를 시작하기 전에 설정하기만 하면 됩니다. (설정을 해제하려고 시도하지 마십시오. 이로 인해 일부 쉘에 문제가 발생할 수 있습니다.)
예를 들어:
set -- -a foo
while getopts a:b: option; do
echo "$option: $OPTARG"
done
set -- -b first -b second
# OPTIND=1
while getopts a:b: option; do
echo "$option: $OPTARG"
done
인쇄
a: foo
b: second
두 번째 루프는 첫 번째 루프가 끝난 곳에서 계속되기 때문에 -b first
.
OPTIND=1
중간 할당의 주석을 해제 하면 예상되는 출력을 얻을 수 있습니다.
a: foo
b: first
b: second
매개변수를 별도로 저장하는 경우 단일 문자열이 구성되는 반면 $@
, args+="-a ${OPTARG} "
명령줄 매개변수 세트는 실제로 다양한 문자열의 목록/배열입니다. 매개변수 자체에 공백이 포함된 경우 차이점이 가장 두드러집니다. 두 개의 인수 집합( -a
, foo bar
)과 ( -a foo
, bar
)이 연결되어 있으며 -a foo bar
후자의 문자열은 구별할 수 없습니다.
대신 배열을 사용하여 매개변수를 고유한 문자열로 저장하세요.
while getopts a:b:d option
do
case "${option}"
in
a) args+=(-a "$OPTARG");;
b) args+=(-b "$OPTARG");;
d) echo 'Option:D';;
esac
done
# ...
./args.sh "${args[@]}"
(바라보다 변수에 저장된 명령을 어떻게 실행할 수 있나요?더 많은 예를 보려면 등)
알아채다,표준 .
(점) 명령소스 스크립트는 매개변수를 사용하지 않지만 소스 스크립트는 $@
기본 스크립트와 동일합니다. (소스 스크립트에서 변경된 내용은 $@
기본 스크립트에 표시됩니다.)
Bash .
/는 source
새로운 인수 세트 전달을 지원 하지만 source filename
인수 세트 없이 호출하면 소스 스크립트는아니요빈 목록을 가져오지만 기본 스크립트에 대한 매개변수가 포함되어 있습니다.
그렇다면 다음과 같이 하세요.
source ./args.sh "${args[@]}"
비어 있지 않은지 확인하는 것이 좋습니다 args
. 아니면 다른 스크립트를 가져오기 전에 기본 스크립트의 매개변수를 재설정하세요. 물론 이렇게 하면 원래 매개변수 세트가 파괴되지만 필요한 경우 먼저 다른 배열에 저장할 수 있습니다.
orig_args=( "$@" ) # if needed
set -- "${args[@]}"
source ./args.sh