현재 저는 다음 요구 사항을 충족하는 Bash 스크립트를 작성 중입니다.
- 다양한 Unix/Linux 플랫폼에서 실행되어야 합니다.
- 짧은 옵션과 (GNU) 긴 옵션을 지원해야 합니다.
나는 이것이 getopts
이식성 측면에서 선호되는 방법이라는 것을 알고 있지만 내가 아는 한 긴 옵션을 지원하지 않습니다.
getopt
긴 옵션이 지원되지만배쉬 가이드다음에 대해 강력히 권장됩니다.
절대로 getopt(1)를 사용하지 마십시오. getopt는 빈 매개변수 문자열이나 공백이 포함된 매개변수를 처리할 수 없습니다. 그것이 존재했던 적이 있다는 것을 잊어 버리십시오.
따라서 여전히 수동 구문 분석 옵션이 있습니다. 이는 오류가 발생하기 쉽고, 상당히 많은 상용구 코드를 생성하며 오류를 직접 처리해야 합니다( getopt(s)
오류 처리를 직접 수행하고 싶습니다).
그렇다면 이 경우 첫 번째 선택은 무엇입니까?
답변1
getopt
vs getopts
종교적인 문제인 것 같습니다. 이의사항 getopt
에 대해서는배쉬 FAQ:
"
getopt
빈 인수 문자열을 처리할 수 없습니다."는 알려진 문제를 나타내는 것 같습니다.임의로 선택할 수 있는매개변수는getopts
전혀 지원되지 않는 것 같습니다(적어도help getopts
Bash 4.2.24를 읽으면). 에서man getopt
:getopt(3)는 빈 선택적 인수로 긴 옵션을 구문 분석할 수 있습니다(짧은 옵션은 아님). getopt(1)은 빈 선택적 인수를 존재하지 않는 것처럼 처리합니다.
많은 "전통적인" 구현이 getopt
공백이 포함된 인수를 구문 분석할 수 없는 것이 사실이지만 util-linux의 구현이나 Busybox에 포함된 구현의 경우는 그렇지 않습니다.
테스트.sh:
#!/usr/bin/env bash getopt -T if [ "$?" != 4 ]; then echo 2>&1 "Wrong version of 'getopt' detected, exiting..." exit 1 fi set -o errexit -o noclobber -o nounset -o pipefail params="$(getopt -o ab:c -l alpha,bravo:,charlie --name "$0" -- "$@")" eval set -- "$params" while true do case "$1" in -a|--alpha) echo alpha shift ;; -b|--bravo) echo "bravo=$2" shift 2 ;; -c|--charlie) echo charlie shift ;; --) shift break ;; *) echo "Not implemented: $1" >&2 exit 1 ;; esac done
달리기:
$ ./test.sh - $ ./test.sh -acb ' whitespace FTW ' alpha charlie bravo= whitespace FTW $ ./test.sh -ab '' -c alpha bravo= charlie $ ./test.sh --alpha --bravo ' whitespace FTW ' --charlie alpha bravo= whitespace FTW charlie
물론 이식성 문제는 여전히 존재합니다. 해당 버전이 존재하지 않는 경우를 결정해야 합니다 getopt
.야그니그리고키스지침 - 사용할 특정 플랫폼용으로만 개발하세요. 개발 시간이 무한대에 가까워질수록 쉘 코드 이식성은 일반적으로 100%에 도달합니다.
답변2
다양한 Unices로 이식 가능해야 한다면 POSIX sh를 사용해야 합니다. AFAIU, 매개변수 처리를 수동으로 롤링하는 것 외에는 선택의 여지가 없습니다.
답변3
이것이 있다getopts_longPOSIX 셸 함수로 작성되어 스크립트에 포함할 수 있습니다.
Linux getopt
(from util-linux
)는 그렇지 않은 경우에도 잘 작동합니다.전통적인모드이며 긴 옵션을 지원하지만 다른 Unices로 포팅해야 하는 경우 옵션이 아닐 수도 있습니다.
getopts
ksh93( ) 및 zsh( ) 의 최신 버전에는 zparseopts
긴 옵션 구문 분석에 대한 지원이 내장되어 있으며 이는 옵션이 될 수 있습니다. 이러한 옵션은 대부분의 Unices에서 사용할 수 있기 때문입니다(일반적으로 기본적으로 설치되지는 않음).
또 다른 옵션은 전체 스크립트를 작성하거나 perl을 호출하여 옵션을 구문 분석하고 추출된 정보를 쉘에 제공함으로써 현재 대부분의 Unices에서 사용할 수 있는 perl
모듈 을 사용하는 것입니다 . 그것은 다음과 같습니다:Getopt::Long
perl
parsed_ops=$(
perl -MGetopt::Long -le '
@options = (
"foo=s", "bar", "neg!"
);
Getopt::Long::Configure "bundling";
$q="'\''";
GetOptions(@options) or exit 1;
for (map /(\w+)/, @options) {
eval "\$o=\$opt_$_";
$o =~ s/$q/$q\\$q$q/g;
print "opt_$_=$q$o$q"
}' -- "$@"
) || exit
eval "$parsed_ops"
# and then use $opt_foo, $opt_bar...
perldoc Getopt::Long
이것이 무엇을 하는지, 그리고 다른 옵션 파서와 어떻게 다른지 알아보세요 .
답변4
이를 지원하는 시스템에서 사용할 수 getopt
있고 지원하지 않는 시스템에 대체를 사용할 수 있습니다.
예를 들어 pure-getopt
GNU를 즉시 대체하기 위해 순수 Bash로 구현되었습니다 getopt
.