getopts는 명령줄 인수를 구문 분석하기 위한 내장 유닉스 쉘 명령입니다. 그것은 getopt의 C 인터페이스를 기반으로 POSIX 유틸리티 구문 안내서를 따르는 명령줄 인수를 처리하도록 설계되었습니다.
getopts의 전신은 Unix System Laboratories의 외부 프로그램 getopt였습니다.
History
원래 getopt는 몇 가지 문제가 있었습니다: 그것은 인수에서 공백 또는 쉘 메타문자를 처리할 수 없었고 오류 메시지의 출력을 비활성화하는 기능이 없었습니다.
getopts는 1986년 유닉스 SVR3과 함께 배포되는 Bourne 쉘에서 처음 도입되었습니다. 그것은 쉘 자체 변수를 현재와 인수 위치, OPTIND 및 OPTARG의 위치를 추적하기 위해 사용하고, 쉘 변수에서 옵션 이름을 반환합니다. Bourne 쉘의 이전 버전은 getopts를 가지지 않았습니다.
1995년에, getopts는 단일 유닉스 사양 버전 1 / X/Open 이식성 안내서 4호에 포함되었습니다. 결과로써, getopts는 이제 Bourne 쉘, KornShell, Almquist 쉘, Bash 및 Zsh를 포함한 쉘에서 사용할 수 있습니다.
getopts 명령은 역시 IBM i 운영 시스템으로 이식되었습니다.
getopt의 현대 사용법은 주로 util-linux의 향상된 구현으로 인해 부분적으로 부활했습니다. BSD getopt를 기반으로 하는 이 버전은 이전 getopt에 대한 두 가지 불만 사항을 수정했을 뿐만 아니라, GNU-스타일의 긴 옵션을 구문 분석하는 기능과 getopts에 부족했던 옵션, 기능에 대해 선택적 인수를 도입했습니다. 다양한 BSD 배포판은, 어쨌든, 이전 구현을 고수했습니다.
Usage
getopt와 getopts의 사용 개요는 C 형제와 유사합니다:
getopt optstring [parameters]
getopts optstring varname [parameters]
- optstring 부분은 C 형제로 같은 형식을 가집니다.
- parameters 부분은 getopt에게 구문 분석하기를 원하는 모든 것을 단순히 받아들입니다. 공통 값은 POSIX 쉘에서 모든 매개변수 "$@"입니다.
- 이 값은 getopts에 존재하지만 드물게 사용되는데, 왜냐하면 그것은 단지 쉘의 매개변수에 접근할 수 있기 때문입니다. 어쨌든, 그것은 파서를 재설정하는 데 유용합니다.
- getopts의 varname 부분은 구문 분석된 옵션을 저장할 쉘 변수의 이름을 지정합니다.
명령을 사용하는 방법은 어쨌든 매우 다양합니다:
- getopt는 단순히 "정규화된" 인수를 나타내는 공백으로-구분된 토큰을 포함하는 플랫 문자열을 반환합니다. 그런-다음 그것을 기본적으로 구문 분석하기 위해 while-루프를 사용합니다.
- getopts는 C getopt처럼 반복적으로 호출됨을 의미합니다. 그것이 인수의 끝에 도달할 때, 그것은 1 (쉘 거짓)을 반환합니다.
Enhancements
In various getopts
2004년 봄 (솔라리스 10 베타 개발)에, getopt()에 대해 libc 구현이 긴 옵션을 지원하도록 향상되었습니다. 결과로써, 이 새로운 기능은 Bourne Shell의 내장 명령 getopts에서도 사용할 수 있었습니다. 이것은 긴 별칭을 지정하는 optstring의 괄호로 묶인 접미사에 의해 트리거됩니다.
KornShell과 Zsh 둘 다는 긴 인수에 대해 확장을 가집니다. 전자는 솔라리스에서 정의되지만, 후자는 개벌적인 zparseopts 명령을 통해 구현됩니다.
KornShell은 추가적으로 - 대신에 +로 시작하는 옵션에 대해 optstring 확장을 추가적으로 구현합니다.
In Linux getopt
getopts에 대한 대안은 getopt, 외부 명령줄 프로그램의 리눅스 향상된 버전입니다.
getopt의 리눅스 향상된 버전은 getopts의 여분의 안전성과 보다 발전된 기능을 가집니다. 그것은 긴 옵션 이름 (예를 들어, --help)을 지원하고 옵션이 모든 피연산자 앞에 나타날 필요는 없습니다 (예를 들어, command operand1 operand2 -a operand3 -b는 getopt의 리눅스 향상된 버전에서 허용되지만, getopts에서는 작동하지 않습니다). 그것은 역시 쉘 (예를 들어, tcsh와 POSIX sh) 및 선택적 인수에 대한 탈출 메타문자를 지원합니다.
Comparison
POSIX getopts |
Solaris getopts |
Unix/BSD getopt |
Linux getopt |
|
쉬운 구문 분석을 위한 분할 옵션 | Yes | Yes | Yes | Yes |
오류 메시지 억제 허용 | Yes | Yes | No | Yes |
공백 및 메타 문자로 안전 | Yes | Yes | No | Yes |
피연산자를 옵션과 혼합되는 것을 허용 | No | Yes | No | Yes |
긴 옵션을 지원 | Emulation | Yes | No | Yes |
선택적 인수 | Error handling | Error handling | No | Yes |
Examples
세 가지 옵션과 0개의 여분의 인수를 취하는 bash에서 Wikipedia 다운로더를 빌드한다고 가정합니다:
wpdown -a article name -l [language] -v
가능할 때, 다음과 같은 긴 인수를 허용합니다:
-a --article
-l --language, --lang
-v --verbose
명확성을 위해, 도움말 텍스트는 포함되어 있지 않고, 임의의 웹 페이지를 다운로드하는 프로그램이 있다고 가정합니다. 게다가, 모든 프로그램의 형식은 다음과 같습니다:
#!/bin/bash
VERBOSE=0
ARTICLE=''
LANG=en
# [EXAMPLE HERE]
if ((VERBOSE > 2)); then
printf '%s\n' 'Non-option arguments:'
printf '%q ' "${remaining[@]]}"
fi
if ((VERBOSE > 1)); then
printf 'Downloading %s:%s\n' "$LANG" "$ARTICLE"
fi
if [[ ! $ARTICLE ]]; then
printf '%s\n' "No articles!">&2
exit 1
fi
save_webpage "https://${LANG}.wikipedia.org/wiki/${ARTICLE}"
Using old getopt
이전 getopt는 선택적 인수를 지원하지 않습니다:
# parse everything; if it fails we bail
args=`getopt 'a:l:v' $*` || exit
# now we have the sanitized args... replace the original with it
set -- $args
while true; do
case $1 in
(-v) ((VERBOSE++)); shift;;
(-a) ARTICLE=$2; shift 2;;
(-l) LANG=$2; shift 2;;
(--) shift; break;;
(*) exit 1;; # error
esac
done
remaining=("$@")
이 스크립트는 역시 그것에서 스페이스 또는 쉘 메타문자 (예를 들어, ? 또는 *)를 갖는 임의의 기사 제목으로도 깨질 것입니다.
Using getopts
getopts는 스크립트에 C 인터페이스의 모양과 느낌을 제공하지만, POSIX에서 선택적 인수가 여전히 없습니다:
#!/bin/sh
while getopts ':a:l:v' opt; do
case $opt in
(v) ((VERBOSE++));;
(a) ARTICLE=$OPTARG;;
(l) LANG=$OPTARG;;
(:) # "optional arguments" (missing option-argument handling)
case $OPTARG in
(a) exit 1;; # error, according to our syntax
(l) :;; # acceptable but does nothing
esac;;
esac
done
shift "$OPTIND"
# remaining is "$@"
더 이상 쉘 옵션을 직접 조작하지 않기 때문에, 더 이상 변경할 필요가 없습니다. 어쨌든, 지금은 나머지 인수를 얻기 위해 슬라이싱 작업을 요구합니다.
--fast를 옵션 -에 대한 인수 fast로 처리함으로써 긴 인수 지원을 에뮬레이트하는 것은 가능하지만 지루합니다.
Using Linux getopt
리눅스 getopt는 출력을 이스케이프하고 "eval" 명령은 쉘이 그것을 해석하도록 해야 합니다. 나머지는 변경되지 않습니다:
# We use "$@" instead of $* to preserve argument-boundary information
ARGS=$(getopt -o 'a:l::v' --long 'article:,language::,lang::,verbose' -- "$@") || exit
eval "set -- $ARGS"
while true; do
case $1 in
(-v|--verbose)
((VERBOSE++)); shift;;
(-a|--article)
ARTICLE=$2; shift 2;;
(-l|--lang|--language)
# handle optional: getopt normalizes it into an empty string
if [ -n "$2" ]; then
LANG=$2; shift;
fi
shift;;
(--) shift; break;;
(*) exit 1;; # error
esac
done
remaining=("$@")
External links
- getopts: process command line arguments – Commands & Utilities Reference, The Single UNIX Specification, Issue 7 from The Open Group