다음 프로그램에 대한 bash 스크립트를 작성할 때 선택적 매개변수/플래그를 포함하는 방법이 혼란스럽습니다.
이 프로그램에는 두 가지 매개변수가 필요합니다.
run_program --flag1 <value> --flag2 <value>
그러나 다음과 같은 몇 가지 선택적 플래그가 있습니다.
run_program --flag1 <value> --flag2 <value> --optflag1 <value> --optflag2 <value> --optflag3 <value> --optflag4 <value> --optflag5 <value>
사용자 매개변수를 허용하도록 bash 스크립트를 실행하고 싶습니다. 사용자가 두 개의 매개변수만 순서대로 입력하면 다음과 같습니다.
#!/bin/sh
run_program --flag1 $1 --flag2 $2
하지만 선택적 매개변수가 포함되면 어떻게 될까요? 내 생각엔 그럴 것 같아
if [ --optflag1 "$3" ]; then
run_program --flag1 $1 --flag2 $2 --optflag1 $3
fi
하지만 3달러 대신 4달러를 받았다면 어떨까요?
답변1
이 기사두 가지 다른 접근 방식 shift
이 표시됩니다 getopts
(그리고 두 접근 방식의 장점과 단점에 대해 논의합니다).
shift
스크립트를 사용하여 보고 $1
, 수행할 작업을 결정한 다음 실행 shift
, 이동 $2
, $1
이동 $3
등 $2
을 수행합니다.
예를 들어:
while :; do
case $1 in
-a|--flag1) flag1="SET"
;;
-b|--flag2) flag2="SET"
;;
-c|--optflag1) optflag1="SET"
;;
-d|--optflag2) optflag2="SET"
;;
-e|--optflag3) optflag3="SET"
;;
*) break
esac
shift
done
getopts
표현식 에서 (짧은) 옵션을 정의 할 수 있습니다 while
.
while getopts abcde opt; do
case $opt in
a) flag1="SET"
;;
b) flag2="SET"
;;
c) optflag1="SET"
;;
d) optflag2="SET"
;;
e) optflag3="SET"
;;
esac
done
분명히 이것은 단지 코드 조각일 뿐이므로 유효성 검사를 생략했습니다. 필수 매개변수인 flag1 및 flag2가 설정되어 있는지 확인하는 것 등입니다.
어떤 방법을 사용하는지는 선호도에 따라 달라집니다. 즉, 스크립트의 이식성을 원하는지, 짧은 옵션(POSIX)만 허용하는지 또는 긴 옵션(GNU)을 원하는지 등입니다.
답변2
배열을 사용하세요.
#!/bin/bash
args=( --flag1 "$1" --flag2 "$2" )
[ "x$3" = xFALSE ] || args+=( --optflag1 "$3" )
[ "x$4" = xFALSE ] || args+=( --optflag2 "$4" )
[ "x$5" = xFALSE ] || args+=( --optflag3 "$5" )
[ "x$6" = xFALSE ] || args+=( --optflag4 "$6" )
[ "x$7" = xFALSE ] || args+=( --optflag5 "$7" )
program_name "${args[@]}"
그러면 공백이 포함된 매개변수가 올바르게 처리됩니다.
[편집] 나는 거의 동일한 구문을 사용하고 있지만 args=( "${args[@]}" --optflag1 "$3" )
G-Man이 더 나은 방법을 생각해냈습니다.
답변3
쉘 스크립트에서 매개변수는 "$1", "$2", "$3" 등입니다. 매개변수 개수는 $#입니다.
스크립트가 옵션을 인식하지 못하는 경우 옵션 감지를 무시하고 모든 인수를 피연산자로 처리할 수 있습니다.
옵션을 식별하려면 내장된 getopts를 사용하세요.
답변4
만약 당신의입력하다옵션은 위치에 따라 다르며(어디에 있는지 알 수 있음) 플래그로 지정되지 않습니다. 그러면 원하는 것은 명령줄을 작성하는 것뿐입니다. 모든 항목에 대한 명령 매개변수를 준비하세요.
FLAG1="--flag1 $1"
FLAG2="--flag2 $2"
OPTFLAG1=""
OPTFLAG2=""
OPTFLAG3=""
if [ xFALSE != x"$3" ]; then
OPTFLAG1="--optflag1 $3"
fi
if [ xFALSE != x"$4" ]; then
OPTFLAG2="--optflag2 $4"
fi
#the same for other flags
#now just run the program
runprogram $FLAG1 $FLAG2 $OPTFLAG1 $OPTFLAG2 $OPTFLAG3
인수가 지정되지 않으면 해당 문자열은 비어 있고 아무것도 확장되지 않습니다. 마지막 줄에는 따옴표가 없습니다. 이는 쉘이 인수를 단어로 분할 --flag1
하고 $1
프로그램에 대한 별도의 인수로 분할하기를 원하기 때문입니다. 물론, 원래 매개변수에 공백이 포함되어 있으면 이것이 잘못됩니다. 이 스크립트를 실행하는 사람이라면 그대로 둘 수 있지만 일반 스크립트인 경우 사용자가 공백이 포함된 항목을 입력하면 예기치 않게 동작할 수 있습니다. 이 문제를 해결하려면 코드를 좀 더 보기 흉하게 만들어야 합니다.
x
테스트의 접두사는 []
대소문자가 있거나 $3
비어 $4
있습니다. 이 경우 bash는 구문 오류 [ FALSE != $3 ]
로 확장되므로 이를 방지하기 위해 다른 임의의 문자를 사용할 수 있습니다. [ FALSE != ]
이는 매우 일반적인 접근 방식이며 많은 스크립트에서 볼 수 있습니다.
확실하게 하기 위해 처음에 OPTFLAG1
이들 항목과 나머지 항목을 설정했지만 ( 이전에 설정한 경우) 환경에서 실제로 선언되지 않은 경우 엄격하게 이 작업을 수행할 필요는 없습니다.""
몇 가지 추가 참고 사항:
- 실제로
runprogram
플래그를 사용하여 동일한 방식으로 매개변수를 받을 수 있습니다. 그것이 우리가John N
부르는 것입니다. 이것이getopts
유용한 곳 입니다 . - 이 목적으로 FALSE를 사용하는 것은 다소 비표준적이고 시간이 오래 걸립니다. 일반적으로 단일 문자(아마도
-
)를 사용하여 null 값을 나타내거나 빈 문자열을 전달합니다(예:""
매개변수에 유효한 값이 아닌 경우). 빈 문자열을 사용하면 테스트가 더 짧아지므로if [ -n "$3" ]
. - 선택적 플래그가 하나만 있거나 서로 관련되어 OPTFLAG2는 가질 수 없지만 OPTFLAG1은 가질 수 없는 경우 설정하고 싶지 않은 플래그를 건너뛸 수 있습니다. 위에서 제안한 것처럼 null 인수를 사용하는 경우
""
어쨌든 후행 null 인수를 건너뛸 수 있습니다.
이 접근 방식은 Makefile에서 옵션이 컴파일러에 전달되는 방식과 거의 유사합니다.
다시 말하지만, 입력에 공백이 포함되어 있으면 보기 흉해집니다.