원문 보기: https://dawoum.duckdns.org/wiki/Getopt
Getopt는 Unix/POSIX 스타일의 명령-줄 옵션을 구문 분석하기 위해 사용되는 C 라이브러리 함수입니다. 그것은 POSIX 사양의 일부이고, 유닉스-계열 시스템에 보편적입니다. 그것은 역시 쉘 스크립트에서 명령줄 인수를 구문 분석하는 유닉스 프로그램의 이름이기도 합니다.
History
명령줄 프로그램과 함께 오랜 문제점은 옵션을 지정하는 방법이었습니다; 초기 프로그램에서는 단일 문자 옵션 (-a), 함께 지정된 여러 옵션 (-abc는 -a -b -c와 동등), 다중-문자 옵션 (-inum), 인수를 갖는 옵션 (-a arg, -inum 3, -a=arg), 및 다양한 접두 문자 (-a, +b, /c)를 포함하여 옵션을 지정하는 많은 방법을 사용했습니다.
getopt 함수는 모든 사람이 의존할 수 있는 공통 인터페이스가 있도록 모든 프로그램이 명령줄 옵션을 구문 분석하기 위해 사용할 수 있는 표준 메커니즘으로 작성되었습니다. 이를테면, 원래 작성자는 단일 문자 옵션, 함께 지정된 여러 옵션, 및 인수를 갖는 옵션 (-a arg 또는 -aarg)에 대한 변형 지원을 선택했으며, 모두 옵션 문자열로 제어할 수 있습니다.
getopt는 적어도 1980년으로 거슬러 올라가고, 1985년 텍사스주 댈러스에서 열린 UNIFORUM 컨퍼런스에서 AT&T에 의해 처음 발표했으며, 퍼블릭 도메인에서 사용할 수 있도록 의도되었습니다. 이후 다른 버전의 Unix (4.3BSD, Linux, 등)에 의해 그것의 버전이 채택되었습니다. 그것은 POSIX.2 표준에서 unistd.h 헤더 파일의 일부로 지정되어 있습니다. 많은 프로그래밍 언어에서 명령줄 옵션을 구문 분석하기 위해 getopt의 파생 버전이 만들어져 왔습니다.
getopt에 대한 POSIX-표준 동반 함수는 getsubopt입니다. 그것은 쉼표-구분된 하위-옵션의 문자열을 구문 분석합니다. 그것은 4.4BSD (1995)에 등장했습니다.
Extensions
getopt는 시스템에 종속된 함수이고, 그 동작은 C 라이브러리에서 구현에 따라 달라집니다. 어쨌든, gnulib와 같은 일부 사용자 정의 구현이 사용될 수 있습니다.
기존 (POSIX 및 BSD) 처리 방식은 첫 번째 비-옵션 인수가 발생할 때 옵션이 종료되고, getopt가 -1을 반환하여 이를 알립니다. 어쨌든, glibc 확장에서는 사용 편의성을 위해 어디에서나 옵션을 허용합니다; getopt는 암묵적으로 인수 벡터를 순열하므로 끝에 비-옵션을 그대로 둡니다. POSIX에는 이미 --에서 -1을 반환하고 그것을 건너뛰는 관례가 있기 때문에, 항상 이식성 있게 옵션-종료 표시자로 사용할 수 있습니다.
GNU 확장, getopt_long은 하나 대신 두 개의 대시에 의해 도입되는 더 읽기 쉬운 다중-문자 옵션의 구문 분석을 허용합니다. 두 개의 대시의 선택은 다중-문자 옵션 (--inum)을 함께 지정된 단일 문자 옵션 (-abc)과 구별하도록 허용합니다. GNU 확장은 역시 인수를 갖는 옵션: --name=arg에 대한 대안적인 형식도 허용합니다. 이 인터페이스는 인기가 있는 것으로 입증되었고, FreeBSD와 Solaris를 포함한 많은 BSD 배포판에서 채택되어 왔습니다. 긴 옵션을 지원하기 위한 대안적인 방법은 Solaris와 Korn Shell (optstring 확장)에서 볼 수 있지만, 인기가 없었습니다.
getopt의 또 다른 공통적인 고급 확장은 인수 구문 분석의 상태를 재설정하는 것입니다; 이것은 options-anyware GNU 확장을 대체하거나, 다양한 레벨에서 다양한 옵션을 갖는 명령줄 인터페이스의 집합을 "계층화"하는 방법으로 유용합니다. 이것은 BSD 시스템에서 optreset 변수를 사용하여 달성되고, GNU 시스템에서 optind를 0으로 설정함으로써 달성됩니다.
Usage
For users
getopt-기반 프로그램에 대해 명령-줄 구문은 POSIX-권장된 Utility Argument Syntax입니다. 간단히 말해서:
- 옵션은 - (하이픈 빼기) 문자로 시작하는 단일-문자 영숫자입니다.
- 옵션은 인수를 취할 수 있으며, 필수 또는 선택 사항이며, 아무것도 취할 수 없습니다.
- 옵션이 인수를 취하도록 지정하기 위해, 옵션 이름 뒤에 :를 포함합니다 (초기 지정 중에만 해당).
- 옵션이 인수를 취할 때, 이것은 같은 토큰이나 다음 토큰에 있을 수 있습니다. 다시 말해서, o가 인수를 취하면, ofoo는 -o foo와 같습니다.
- 마지막이 아닌 옵션이 인수를 취하지 않는 한, 여러 옵션이 함께 연결될 수 있습니다. 만약 a와 b가 인수를 취하지 않고, 반면 e는 선택적 인수를 취하면, -abe는 -a -b -e와 같지만, -bea는 이전 규칙으로 인해 -b -e a와 같지 않습니다.
- 모든 옵션은 비-옵션 인수보다 앞에 옵니다 (GNU 확장의 경우 제외). --는 항상 옵션의 끝을 나타냅니다.
구문에 대한 확장에는 GNU 규칙과 Sun의 CLIP 사양이 포함됩니다.
For programmers
GNU로부터 getopt 매뉴얼은 getopt에 대한 그러한 사용법을 지정합니다:
#include <unistd.h>
int getopt(int argc, char * const argv[],
const char *optstring);
여기서 argc와 argv는 C main 함수 프로토타입에서와 정확하게 동일하게 정의됩니다; 즉, argc는 argv 문자열-의-배열의 길이를 나타냅니다. optstring에는 찾아야 할 옵션 (W를 제외한 정규 영숫자)과 인수를 수용할 옵션 (콜론)에 대한 사양이 포함되어 있습니다. 예를 들어, "vf::o:"는 인수-없는 v, 선택적-인수 f, 및 필수-인수 o의 세 가지 옵션을 나타냅니다. GNU는 여기서 긴 옵션 동의어에 대한 W 확장을 구현합니다.
getopt 자체는 옵션 문자이거나 옵션-의-종료에 대해 -1인 정수를 반환합니다. 관용구는 while-루프를 옵션을 살펴보기 위해 사용하고, switch-case 문을 옵션을 선택하고 작업하기 위해 사용하는 것입니다. 이 기사의 예제 섹션을 참조하십시오.
프로그램에 추가 정보를 전달하기 위해 프로그램은 몇 개의 글로벌 extern 변수를 참조하여 getopt에서 정보를 가져옵니다:
extern char *optarg;
extern int optind, opterr, optopt;
optarg 현재 옵션의 인수에 대한 포인터 (만약 있으면). (다시) 구문 분석을 시작할 위치를 제어하기 위해데 사용될 수 있습니다. optind 여기서 getopt는 현재 argv에서 보고 있습니다. opterr getopt가 오류 메시지를 인쇄해야 하는지 여부를 제어하는 부울 스위치입니다. optopt 만약 인식할 수 없는 옵션이 발생하면, 해당 인식할 수 없는 문자의 값입니다.
GNU 확장 getopt_long 인터페이스는 비슷하지만, 다른 헤더 파일에 속하고 긴 옵션의 "짧은" 이름과 몇 가지 여분의 제어를 정의하기 위한 여분의 옵션을 사용합니다. 만약 짧은 이름이 정의되지 않으면, getopt는 대신 longindex 포인터에 옵션 구조를 참조하는 인덱스를 넣습니다.
#include <getopt.h>
int getopt_long(int argc, char * const argv[],
const char *optstring,
const struct option *longopts, int *longindex);
Examples
Using POSIX standard getopt
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <unistd.h> /* for getopt */
int main (int argc, char **argv) {
int c;
int digit_optind = 0;
int aopt = 0, bopt = 0;
char *copt = 0, *dopt = 0;
while ((c = getopt(argc, argv, "abc:d:012")) != -1) {
int this_option_optind = optind ? optind : 1;
switch (c) {
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind) {
printf ("digits occur in two different argv-elements.\n");
}
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
aopt = 1;
break;
case 'b':
printf ("option b\n");
bopt = 1;
break;
case 'c':
printf ("option c with value '%s'\n", optarg);
copt = optarg;
break;
case 'd':
printf ("option d with value '%s'\n", optarg);
dopt = optarg;
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
printf ("non-option ARGV-elements: ");
while (optind < argc) {
printf ("%s ", argv[optind++]);
}
printf ("\n");
}
exit (0);
}
Using GNU extension getopt_long
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <getopt.h> /* for getopt_long; POSIX standard getopt is in unistd.h */
int main (int argc, char **argv) {
int c;
int digit_optind = 0;
int aopt = 0, bopt = 0;
char *copt = 0, *dopt = 0;
static struct option long_options[] = {
/* NAME ARGUMENT FLAG SHORTNAME */
{"add", required_argument, NULL, 0},
{"append", no_argument, NULL, 0},
{"delete", required_argument, NULL, 0},
{"verbose", no_argument, NULL, 0},
{"create", required_argument, NULL, 'c'},
{"file", required_argument, NULL, 0},
{NULL, 0, NULL, 0}
};
int option_index = 0;
while ((c = getopt_long(argc, argv, "abc:d:012",
long_options, &option_index)) != -1) {
int this_option_optind = optind ? optind : 1;
switch (c) {
case 0:
printf ("option %s", long_options[option_index].name);
if (optarg) {
printf (" with arg %s", optarg);
}
printf ("\n");
break;
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind) {
printf ("digits occur in two different argv-elements.\n");
}
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
aopt = 1;
break;
case 'b':
printf ("option b\n");
bopt = 1;
break;
case 'c':
printf ("option c with value '%s'\n", optarg);
copt = optarg;
break;
case 'd':
printf ("option d with value '%s'\n", optarg);
dopt = optarg;
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
printf ("non-option ARGV-elements: ");
while (optind < argc) {
printf ("%s ", argv[optind++]);
}
printf ("\n");
}
exit (0);
}
In Shell
쉘 스크립트 프로그래머는 공통적으로 옵션을 제공하는 일관된 방식을 제공하고 싶어합니다. 이 목표를 달성하기 위해, 그것들은 getopts로 전환하고 자체 언어로 이식하려고 합니다.
포팅에서 첫 시도는 Unix System Laboratories (USL)에 의해 구현된 프로그램 getopt였습니다. 이 버전은 인용 및 쉘 메타문자를 처리할 수 없었는데, 왜냐마현 인용 시도가 전혀 나타나지 않았기 때문입니다. 그것은 FreeBSD로 상속되어 왔습니다.
1986년에, USL은 메타문자와 공백 주변에서 안전하지 않은 것은 더 이상 용납할 수 없다고 결정하고, 그들은 대신 Unix SVR3 Bourne Shell에 내장된 getopts 명령을 만들었습니다. 명령을 쉘에 빌드하는 이점은 이제 쉘의 변수에 접근할 수 있으므로, 따옴표 없이도 값을 안전하게 작성할 수 있다는 것입니다. 그것은 쉘의 자체 변수를 현재 및 인수 위치, OPTIND와 OPTARG의 위치를 추적하기 위해 사용하도, 쉘 변수에서 옵션 이름을 반환합니다.
1995년에, getopts는 Single UNIX Specification 버전 1 / X/Open 이식성 지침 문제점 4에 포함되었습니다. 이제 POSIX 쉘 표준의 일부, getopts는 POSIX-호환이 되도록 시도하는 다른 많은 쉘에 널리 퍼졌습니다.
getopt는 util-linux가 이스케이프에 의해 모든 이전 getopt의 문제를 수정한 향상된 버전을 출시할 때까지 기본적으로 잊혀졌습니다. 그것은 역시 GNU의 긴 옵션 이름도 지원합니다. 다른 한편, 긴 옵션은 다른 쉘에서 getopts 명령에서 거의 구현되지 않았으며, ksh93은 예외입니다.
In other languages
getopt는 공통적인 POSIX 명령 인수 구조의 간결한 설명이고, 그것은 명령줄에서 자신과 사용자에게 비슷한 인터페이스를 제공하기 위해 프로그래머들에 의해 널리 복제되고 있습니다.
- C: 비-POSIX 시스템은 C 라이브러리에서 getopt를 제공하지 않지만, gnulib 및 MinGW (둘 다 GNU-스타일 허용)와 일부 최소한의 라이브러리는 기능을 제공하기 위해 사용될 수 있습니다. 대안적인 인터페이스도 존재합니다:
- popt 라이브러리는, RPM 패키지 관리자에 의해 사용되며, 재진입 가능하다는 추가적인 이점이 있습니다.
- glibc와 gnulib에서 argp 함수의 가족은 좀 더 편리하고 모듈화된 기능을 제공합니다.
- D 프로그래밍 언어: D 표준 라이브러리에서 getopt 모듈을 가집니다.
- Go: flag 패키지와 함께 제공되며, 이는 긴 플래그 이름을 허용합니다. getopt 패키지는 C 함수에 더 가까운 처리를 지원합니다. 원래 POSIX 패키지에 훨씬 더 가까운 인터페이스를 제공하는 또 다른 getopt 패키지도 있습니다.
- Haskell: System.Console.GetOpt와 함께 제공되며, 이는 필수적으로 GNU getopt 라이브러리의 Haskell 포트입니다.
- Java: Java 표준 라이브러리에는 getopt 구현이 없습니다. GNU getopt에서 이식된 gnu.getopt.Getopt 및 Apache Commons CLI를 포함하여 여러 오픈-소스 모듈이 있습니다.
- Lisp: 공통 표준 라이브러리가 없는 여러 가지 방언이 있습니다. Lisp의 일부 방언에 대한 getopt의 일부 타사 구현이 있습니다. Common Lisp에는 눈에 띄는 타사 구현이 있습니다.
- Free Pascal: GetOpts라는 표준 단위 중 하나로 자체 구현이 있습니다. 그것은 모든 플랫폼에서 지원됩니다.
- Perl programming language: 표준 라이브러리에는 getopt의 두 가지 별도 파생: Getopt::Long and Getopt::Std가 있습니다.
- PHP: getopt 함수가 있습니다.
- Python: C의 getopt 및 GNU 확장을 기반으로 하는 표준 라이브러리에 모듈이 포함되어 있습니다. Python의 표준 라이브러리에는 사용하기 편리한 옵션을 구문 분석하는 다른 모듈도 포함되어 있습니다.
- Ruby: 표준 라이브러리인 GetoptLong에 getopt_long의 구현이 있습니다. Ruby는 역시 표준 라이브러리에 더 정교하고 편리한 인터페이스를 갖는 모듈을 가지고 있습니다. 원래 getopt 인터페이스의 타사 구현은 사용될 수 있습니다.
- .NET Framework: 표준 라이브러리에 getopt 기능이 없습니다. 타사 구현은 사용될 수 있습니다.
External links
- POSIX specification
- GNU getopt manual
- Full getopt port for Unicode and Multibyte Microsoft Visual C, C++, or MFC projects