현재 다음 요구 사항이있는 Bash 스크립트를 작성 중입니다.
- 다양한 유닉스 / 리눅스 플랫폼에서 실행되어야합니다
- 단기 및 (GNU) 장기 옵션을 모두 지원해야합니다.
그 알 getopts
은 긴 옵션을 지원하지 않는 휴대하지만 AFAIK의 측면에서 선호하는 방법이 될 것입니다.
getopt
긴 옵션을 지원하지만 BashGuide 는 강력하게 권장합니다.
getopt (1)를 사용하지 마십시오. getopt는 빈 인수 문자열 또는 공백이 포함 된 인수를 처리 할 수 없습니다. 그것이 존재했음을 잊지 마십시오.
따라서 수동 구문 분석 옵션이 여전히 있습니다. 이것은 오류가 발생하기 쉽고 보일러 코드를 생성하며 직접 오류를 처리해야합니다 ( getopt(s)
오류 처리는 자체적으로 추측 합니다).
그렇다면이 경우 선호되는 선택은 무엇입니까?
답변
다양한 Unices에 이식 할 수 있어야한다면 POSIX sh를 고수해야합니다. 그리고 AFAIU는 당신이 손으로 롤링 인수 처리를 할 수 밖에 없습니다.
답변
getopt
vs getopts
는 종교적인 문제인 것 같습니다. Bash FAQgetopt
에서 반대 의견에 대해서는 :
-
”
getopt
빈 인수 문자열을 처리 할 수 없습니다 ” 는 선택적 인수 에 대한 알려진 문제를 나타내는 것으로 보이며, 이는getopts
전혀 지원하지 않는 것처럼 보입니다 (적어도help getopts
Bash 4.2.24의 읽기 에서). 보낸 사람man getopt
:getopt (3)은 빈 선택적 인수가 제공되는 선택적 인수로 긴 옵션을 구문 분석 할 수 있지만 짧은 옵션의 경우에는이를 수행 할 수 없습니다. 이 getopt (1)은 비어있는 선택적 인수를 존재하지 않는 것처럼 처리합니다.
” getopt
공백 된 공백이있는 […] 인수를 처리 할 수 없습니다 ” 는 어디에서 왔는지 모르지만 테스트 해 보겠습니다.
-
test.sh :
#!/usr/bin/env bash 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
나에게 확인하고 친구처럼 보이지만 누군가 내가 어떻게 문장을 완전히 오해했는지 보여줄 것입니다. 물론 이식성 문제는 여전히 유효합니다. Bash가 오래되었거나없는 플랫폼에 투자 할 가치가있는 시간을 결정해야합니다. 내 팁은 YAGNI 및 KISS 지침 을 사용하는 것입니다. 사용할 예정인 특정 플랫폼에 대해서만 개발하십시오. 개발 시간이 무한대로 진행됨에 따라 셸 코드 이식성은 일반적으로 100 %에 이릅니다.
답변
이 getopts_long 은 스크립트에 임베드 할 수있는 POSIX 쉘 함수로 작성되었습니다.
Linux getopt
(from util-linux
)는 기존 모드가 아니고 긴 옵션을 지원할 때 올바르게 작동 하지만 다른 Unices로 이식해야하는 경우에는 옵션이 아닐 수 있습니다.
최신 버전의 ksh93 ( getopts
) 및 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
는 무엇을 할 수 있는지과는 다른 옵션을 파서 어떻게 다른지.
답변
이 문제에 대한 모든 논의는 구문 분석 코드를 수동으로 작성하는 옵션을 강조 표시 한 후에 만 기능과 이식성을 확신 할 수 있습니다. 사용하기 쉬운 오픈 소스 코드 생성기로 생성하고 다시 생성 할 수있는 코드를 작성하지 않는 것이 좋습니다. 문제에 대한 명확한 답변을 제공하도록 설계된 Argbash를 사용하십시오 . 명령 줄 응용 프로그램 , 온라인 또는 Docker 이미지 로 사용할 수 있는 잘 문서화 된 코드 생성기 입니다.
bash 라이브러리에 대해 조언합니다. 일부 라이브러리는 사용 getopt
하기가 어렵고 읽을 수없는 거대한 셸 Blob을 스크립트와 함께 번들로 묶는 것은 고통 스럽습니다.
답변
getopt
이를 지원하는 시스템에서 사용 하고 지원하지 않는 시스템에서는 대체를 사용할 수 있습니다.
예를 들어 pure-getopt
순수 Bash로 구현되어 GNU를 대체 할 수 있습니다 getopt
.