getopt
Getopt to funkcja biblioteki C używana do analizowania opcji wiersza poleceń w stylu Unix/POSIX. Jest częścią POSIX i jest uniwersalna dla systemów uniksopodobnych . Jest to również nazwa programu uniksowego do analizowania argumentów wiersza poleceń w skryptach powłoki.
Historia
Od dawna problemem związanym z programami wiersza poleceń był sposób określania opcji; wczesne programy wykorzystywały wiele sposobów, w tym opcje jednoznakowe ( -a
), wiele opcji określonych razem ( -abc
jest równoważne z -a -b -c
), opcje wieloznakowe ( -inum
), opcje z argumentami ( -a arg
, -inum 3
, -a=arg
) i różne znaki prefiksu ( -a
, +b
, /c
).
Funkcja getopt została napisana jako standardowy mechanizm, którego wszystkie programy mogłyby używać do analizowania opcji wiersza poleceń, tak aby istniał wspólny interfejs, na którym wszyscy mogliby polegać. W związku z tym oryginalni autorzy wybrali spośród odmian obsługę opcji jednoznakowych, wielu opcji określonych razem oraz opcji z argumentami ( -a arg
lub -aarg
), wszystkie kontrolowane przez ciąg opcji.
getopt pochodzi z co najmniej 1980 roku i został po raz pierwszy opublikowany przez AT&T na konferencji UNIFORUM w 1985 roku w Dallas w Teksasie z zamiarem udostępnienia go jako domeny publicznej. [ potrzebne źródło ] Jego wersje zostały później przechwycone przez inne odmiany Uniksa ( 4.3BSD , Linux , itp.). Jest określony w POSIX.2 jako część pliku nagłówkowego unistd.h . Pochodne getopt zostały stworzone dla wielu języków programowania w celu analizowania opcji wiersza poleceń.
Rozszerzenia
getopt jest funkcją zależną od systemu, a jej zachowanie zależy od implementacji w bibliotece C. Dostępne są jednak niektóre niestandardowe implementacje, takie jak gnulib .
Konwencjonalna obsługa (POSIX i BSD) polega na tym, że opcje kończą się, gdy napotkany zostanie pierwszy argument nie będący opcją, a getopt zwróci -1, aby to zasygnalizować. Jednak w glibc opcje są dozwolone w dowolnym miejscu dla ułatwienia użycia; getopt niejawnie permutuje wektor argumentów, więc na końcu nadal pozostawia brak opcji. Ponieważ POSIX ma już konwencję zwracania -1 na --
i pomijania go, zawsze można go używać jako przenośnego znacznika końca opcji.
Rozszerzenie GNU , getopt_long , umożliwia analizowanie bardziej czytelnych, wieloznakowych opcji, które są wprowadzane przez dwie kreski zamiast jednej. Wybór dwóch kresek umożliwia odróżnienie opcji wieloznakowych ( --inum ) od opcji jednoznakowych określonych razem (
-abc
). Rozszerzenie GNU pozwala również na alternatywny format opcji z argumentami: --name=arg
. Ten interfejs okazał się popularny i został przyjęty (bez permutacji) przez wiele dystrybucji BSD, w tym FreeBSD , a także Solaris . Alternatywny sposób obsługi długich opcji jest widoczny w Solarisie i Korn Shell (rozszerzanie optstring ), ale nie był tak popularny.
Innym powszechnym zaawansowanym rozszerzeniem getopt jest resetowanie stanu analizowania argumentów; jest to przydatne jako zamiennik rozszerzenia GNU options-anyware lub jako sposób na „warstwę” zestawu interfejsu wiersza poleceń z różnymi opcjami na różnych poziomach. Osiąga się to w systemach BSD za pomocą optreset , aw systemach GNU przez ustawienie optind na 0.
Wspólną funkcją towarzyszącą getopt
jest getsubopt
. Analizuje ciąg opcji podrzędnych oddzielonych przecinkami.
Stosowanie
Dla użytkowników
Składnia wiersza poleceń dla programów opartych na getopt to zalecana przez POSIX składnia Utility Argument. W skrócie:
- Opcje to pojedyncze znaki alfanumeryczne poprzedzone znakiem
-
(myślnik-minus). - Opcje mogą przyjąć argument, obowiązkowy lub opcjonalny, lub żaden.
- Aby określić, że opcja przyjmuje argument, należy dołączyć
:
po nazwie opcji (tylko przy wstępnej specyfikacji) - Gdy opcja przyjmuje argument, może to być ten sam token lub następny. Innymi słowy, jeśli
o
przyjmuje argument,-ofoo
jest tym samym co-o foo
. - Wiele opcji można łączyć ze sobą, o ile te, które nie są ostatnimi, nie są argumentami. Jeśli
aib
nie
przyjmują żadnych argumentów, podczas gdye
przyjmuje opcjonalny argument,-abe
jest tym samym co-a -b -e
, ale-bea
nie jest tym samym co-b -ea
ze względu na poprzednią regułę. - Wszystkie opcje poprzedzają argumenty nie będące opcjami (z wyjątkiem w rozszerzeniu GNU).
--
zawsze oznacza koniec opcji.
Rozszerzenia dotyczące składni obejmują konwencję GNU i specyfikację CLIP firmy Sun.
Dla programistów
Podręcznik getopt z GNU określa takie użycie dla getopt:
#include <unistd.h> int getopt ( int argc , char * const argv [], const char * optstring );
Tutaj argc i argv są zdefiniowane dokładnie tak, jak w prototypie głównej funkcji C; tj. argc wskazuje długość tablicy łańcuchów argv. Ciąg optstring zawiera specyfikację, jakich opcji szukać (zwykłe znaki alfanumeryczne z wyjątkiem W ) i jakie opcje akceptować argumenty (dwukropki). Na przykład „vf::o:” odnosi się do trzech opcji: bezargumentowej v , opcjonalnego argumentu f i obowiązkowego argumentu o . GNU implementuje tutaj W dla długich synonimów opcji.
getopt zwraca liczbę całkowitą, która jest albo znakiem opcji, albo -1 dla końca opcji. Idiom polega na użyciu pętli while do przeglądania opcji i użyciu instrukcji switch-case do wybierania opcji i działania na nich. Zobacz przykładową sekcję tego artykułu.
Aby przekazać dodatkowe informacje z powrotem do programu, program odwołuje się do kilku globalnych zmiennych zewnętrznych w celu pobrania informacji z
getopt
:
extern char * optarg ; extern int optind , opterr , optopt ;
- optarg
- Wskaźnik do argumentu bieżącej opcji, jeśli jest obecny. Może być używany do kontrolowania, gdzie rozpocząć parsowanie (ponownie).
- optind
- Gdzie getopt aktualnie patrzy w argv .
- opterr
- Przełącznik logiczny określający, czy getopt powinien drukować komunikaty o błędach.
- otopt
- Jeśli wystąpi nierozpoznana opcja, wartość tego nierozpoznanego znaku.
Interfejs GNU getopt_long jest podobny, chociaż należy do innego pliku nagłówkowego i ma dodatkową opcję definiowania „krótkich” nazw długich opcji oraz kilka dodatkowych elementów sterujących. Jeśli krótka nazwa nie jest zdefiniowana, getopt zamiast tego umieści indeks odnoszący się do struktury opcji we longindex .
#include <getopt.h> int getopt_long ( int argc , char * const argv [], const char * optstring , const struct opcja * longopts , int * longindex );
Przykłady
Korzystanie ze standardowego getopt POSIX
0
0 0
0 0
0
0
#include <stdio.h> /* dla printf */ #include <stdlib.h> /* dla wyjścia */ #include <unistd.h> /* dla getopt */ int main ( int argc , char ** argv ) { int c ; int cyfra_opcja = ; int aopt = , bopt = ; char * kopt = , * dopt = ; while (( c = getopt ( argc , argv , "abc:d:012" )) != -1 ) { int this_option_optind = optind ? opcja wyboru : 1 ; switch ( c ) { case '0' : case '1' : case '2' : if ( digit_optind != && digit_optind != this_option_optind ) { printf ( "cyfry występują w dwóch różnych elementach argv. \n " ); } optymalizacja_cyfry = optymalizacja_ta_opcja ; printf ( "opcja %c \n " , c ); przerwa ; case 'a' : printf ( "opcja a \n " ); aopt = 1 ; przerwa ; case 'b' : printf ( "opcja b \n " ); bopt = 1 ; przerwa ; case 'c' : printf ( "opcja c o wartości '%s' \n " , optarg ); kopt = optarg ; przerwa ; case 'd' : printf ( "opcja d o wartości '%s' \n " , optarg ); dopt = optarg ; przerwa ; sprawa '?' : przerwa ; domyślnie : printf ( "?? getopt zwrócił kod znaku 0%o ?? \n " , c ); } } if ( optind < argc ) { printf ( "nieopcjonalne elementy ARGV: " ); while ( optind < argc ) { printf ( "%s " , argv [ optind ++ ]); } printf ( " \n " ); } wyjdź ( ); }
Korzystanie z rozszerzenia GNU getopt_long
0
0 0
0 0
0
0
0
0
0
0 0
0
0
0
0
#include <stdio.h> /* dla printf */ #include <stdlib.h> /* dla wyjścia */ #include <getopt.h> /* dla getopt_long; Getopt w standardzie POSIX znajduje się w unistd.h */ int main ( int argc , char ** argv ) { int c ; int cyfra_opcja = ; int aopt = , bopt = ; char * kopt = , * dopt = ; static struct opcja long_options [] = { /* NAZWA KRÓTKA NAZWA FLAGI ARGUMENTU */ { "dodaj" , wymagany_argument , NULL , }, { "dołącz" , brak_argumentów , NULL , }, { "usuń" , wymagany_argument , NULL , }, { "verbose" , no_argument , NULL , }, { "create" , wymagane_argument , NULL , 'c' }, { "plik" , wymagany_argument , NULL , }, { NULL , , NULL , } }; int indeks_opcji = ; while (( c = getopt_long ( argc , argv , "abc:d:012" , long_options & option_index )) ! = -1 ) { int this_option_optind = optind ? opcja wyboru : 1 ; switch ( c ) { case : printf ( "opcja %s" , long_options [ indeks_opcji ]. nazwa ); if ( optarg ) { printf ( " with arg %s" , optarg ); } printf ( " \n " ); przerwa ; przypadek '0' : przypadek '1' : przypadek '2' : if ( opt_cyfry != && optym_cyfr != opcja_opcji_ta ) { printf ( "cyfry występują w dwóch różnych elementach argv. \n " ); } cyfra_opcja = ta_opcja_opcja ; printf ( "opcja %c \n " , c ); przerwa ; case 'a' : printf ( "opcja a \n " ); aopt = 1 ; przerwa ; case 'b' : printf ( "opcja b \n " ); bopt = 1 ; przerwa ; case 'c' : printf ( "opcja c o wartości '%s' \n " , optarg ); kopt = optarg ; przerwa ; case 'd' : printf ( "opcja d o wartości '%s' \n " , optarg ); dopt = optarg ; przerwa ; sprawa '?' : przerwa ; domyślnie : printf ( "?? getopt zwrócił kod znaku 0%o ?? \n " , c ); } } if ( optind < argc ) { printf ( "nieopcjonalne elementy ARGV: " ); while ( optind < argc ) { printf ( "%s " , argv [ optind ++ ]); } printf ( " \n " ); } wyjdź ( ); }
W skorupkach
Programiści skryptów powłoki zwykle chcą zapewnić spójny sposób dostarczania opcji. Aby osiągnąć ten cel, zwracają się do getopts i starają się przenieść go na swój własny język.
Pierwszą próbą przeniesienia był program getopt , wdrożony przez Unix System Laboratories (USL). Ta wersja nie była w stanie poradzić sobie z cytowaniem i metaznakami powłoki, ponieważ nie wykazuje żadnych prób cytowania. Został odziedziczony po FreeBSD.
W 1986 roku firma USL zdecydowała, że niebezpieczeństwo związane z metaznakami i białymi znakami nie jest już akceptowane i zamiast tego stworzyło wbudowane polecenie getopts dla Unix SVR3 Bourne Shell. Zaletą wbudowania polecenia w powłokę jest to, że ma ono teraz dostęp do zmiennych powłoki, więc wartości mogą być bezpiecznie zapisywane bez cytowania. Używa własnych zmiennych powłoki do śledzenia pozycji bieżących i pozycji argumentów, OPTIND i OPTARG , i zwraca nazwę opcji w zmiennej powłoki.
W 1995 getopts
został włączony do Single UNIX Specification version 1 / X/Open Portability Guidelines, wydanie 4. Teraz, jako część standardu powłoki POSIX, getopts rozprzestrzenił się daleko w wielu innych powłokach próbujących być zgodnych z POSIX.
getopt został w zasadzie zapomniany, dopóki util-linux nie wyszedł z ulepszoną wersją, która naprawiła wszystkie stare problemy getopt przez ucieczkę. Obsługuje również długie nazwy opcji GNU. Z drugiej strony, długie opcje były rzadko implementowane w getopts
w innych powłokach, z wyjątkiem ksh93 .
W innych językach
getopt to zwięzły opis wspólnej struktury argumentów poleceń POSIX i jest szeroko powielany przez programistów starających się zapewnić podobny interfejs, zarówno dla siebie, jak i dla użytkownika w wierszu poleceń.
- C: systemy inne niż POSIX nie dostarczają
getopt
w bibliotece C, ale gnulib i MinGW (oba akceptują styl GNU), jak również niektóre bardziej minimalne biblioteki, mogą być użyte do zapewnienia tej funkcjonalności. Istnieją również alternatywne interfejsy:- Biblioteka
popt
, używana przez menedżera pakietów RPM , ma tę dodatkową zaletę, że jest reentrant . - Rodzina funkcji
argp
w bibliotekach glibc i gnulib zapewnia większą wygodę i modułowość.
- Biblioteka
- Język programowania D : ma moduł getopt w standardowej bibliotece D.
-
Go : jest dostarczany z pakietem
flag
, który pozwala na długie nazwy flag. Pakietgetopt
obsługuje przetwarzanie bliższe funkcji C. Istnieje również innygetopt
zapewniający interfejs znacznie bliższy oryginalnemu pakietowi POSIX. - Haskell : zawiera System.Console.GetOpt, który jest zasadniczo portem Haskella biblioteki GNU getopt.
- Java : W standardowej bibliotece Java nie ma implementacji getopt. Istnieje kilka modułów open source, w tym gnu.getopt.Getopt, który jest przeniesiony z GNU getopt, oraz Apache Commons CLI.
- Lisp : ma wiele różnych dialektów bez wspólnej biblioteki standardowej. Istnieje kilka zewnętrznych implementacji getopt dla niektórych dialektów Lispa. Common Lisp ma wybitną implementację strony trzeciej.
- Free Pascal : ma własną implementację jako jedną ze swoich standardowych jednostek o nazwie GetOpts. Jest obsługiwany na wszystkich platformach.
- Język programowania Perl : ma dwie oddzielne pochodne getopt w swojej standardowej bibliotece: Getopt::Long i Getopt::Std.
- PHP : ma funkcję getopt.
- Python : zawiera moduł w swojej standardowej bibliotece oparty na rozszerzeniach getopt i GNU języka C. Standardowa biblioteka Pythona zawiera również inne moduły do analizowania opcji, które są wygodniejsze w użyciu.
- Ruby : ma implementację getopt_long w swojej standardowej bibliotece GetoptLong. Ruby ma również moduły w swojej standardowej bibliotece z bardziej wyrafinowanym i wygodnym interfejsem. Dostępna jest implementacja oryginalnego interfejsu getopt innej firmy.
- .NET Framework : nie ma funkcji getopt w swojej standardowej bibliotece. Dostępne są implementacje innych firm.
Linki zewnętrzne
- Specyfikacja POSIX
- Podręcznik GNU getopt
- Pełny port getopt dla projektów Unicode i Multibyte Microsoft Visual C, C++ lub MFC