Dlaczego można pominąć spacje między opcjami i parametrami?

16

Na przykład:

xargs -n 1

jest taki sam jak

xargs -n1

Ale jeśli spojrzysz na stronę man , opcja jest wymieniona jako -n max-args, co oznacza, że ​​przestrzeń ma zostać zachowana. Nie ma nic w skróconej formie -n max-args .

Dzieje się tak również w przypadku wielu innych narzędzi systemu Linux.

Jak to się nazywa w systemie Linux? Czy wszystkie narzędzia obsługują skróconą formę (ale nigdy nie dokumentują jej na stronie podręcznika)?

J.Joe
źródło
1
12.1.2.a to część historii; Przysięgam, że jest już dobre pytanie na ten temat, ale jeszcze go nie znalazłem.
2
@drewbenn inne pytanie, o którym myślisz, mogło być moje: unix.stackexchange.com/q/188046/41515

Odpowiedzi:

12

Kiedy piszesz bit parsowania wiersza poleceń swojego kodu, określasz, które opcje przyjmują argumenty, a które nie. Na przykład w skrypcie powłoki akceptującym -hopcję (na przykład pomoc) i -aopcję, która powinna przyjąć argument, robisz

opt_h=0     # default value
opt_a=""

while getopts 'a:h' opt; do
    case $opt in
        h)  opt_h=1 ;;
        a)  opt_a="$OPTARG" ;;
    esac
done

echo "h: $opt_h"
echo "a: $opt_a"

a:hBit mówi „Czekam analizować dwie opcje, -ai -h, i -apowinna podjąć argument” (jest to :po ato mówi parser który -apobiera argumentu).

Dlatego nigdy nie ma dwuznaczności, gdzie kończy się opcja, gdzie zaczyna się jej wartość, a gdzie zaczyna się kolejna.

Uruchamianie:

$ bash test.sh -h -a hello
h: 1
a: hello

$ bash test.sh -h -ahello
h: 1
a: hello

$ bash test.sh -hahello
h: 1
a: hello

Właśnie dlatego przez większość czasu nie powinieneś pisać własnego parsera wiersza poleceń do analizowania opcji.

W tym przykładzie jest tylko jeden przypadek, który jest trudny. Analiza zwykle kończy się przy pierwszej opcji, więc gdy w wierszu polecenia masz elementy wyglądające jak opcje:

$ bash test.sh -a hello -world
test.sh: illegal option -- w
test.sh: illegal option -- o
test.sh: illegal option -- r
test.sh: illegal option -- l
test.sh: illegal option -- d
h: 0
a: hello

Następujące rozwiązuje, że:

$ bash test.sh -a hello -- -world
h: 0
a: hello

Te --sygnały końca opcji wiersza poleceń, a -worldbit zostaje w programie robić co chce z (to jest w jednej ze zmiennych pozycyjnych).

Tak przy okazji, usuwasz plik z myślnikiem na początku jego nazwy za pomocą rm.

EDYCJA :

Narzędzia napisane w wywołaniu C getopt()(zadeklarowane w unistd.h), które działają prawie tak samo. W rzeczywistości, wszyscy wiemy, bashfunkcja getoptsmoże być realizowana za pomocą wywołanie funkcji biblioteki C getopt(). Perl, Python i inne języki mają podobne biblioteki parsujące wiersze poleceń i najprawdopodobniej przeprowadzają parsowanie w podobny sposób.

Niektóre z tych getopti getoptpodobnych procedur bibliotecznych obsługują również „długie” opcje. Są one zwykle poprzedzone podwójnym myślnikiem ( --), a długie opcje, które pobierają argumenty, często robią to po znaku równości, na przykład --block-size=SIZEopcja [niektóre implementacje] dunarzędzia (które pozwala również na -B SIZEokreślenie tej samej rzeczy).

Powodem, dla którego podręczniki są często pisane, aby pokazać odstęp między krótkimi opcjami i ich argumentami, jest prawdopodobnie czytelność.

EDYCJA : Naprawdę stare narzędzia, takie jak ddi tarnarzędzia, mają przed sobą opcje bez myślników. Wynika to wyłącznie z przyczyn historycznych i dla zachowania zgodności z oprogramowaniem, które polega na tym, że działają w ten właśnie sposób. tarNarzędzie zyskał zdolność do podejmowania opcje z kreskami w ostatnich czasach. Podręcznik BSD do tarwywoływania opcji w starym stylu dla „flag pakietowych”.

Kusalananda
źródło
Ta funkcja może wydawać się łatwa do wdrożenia w skryptach bash. Ale myślę, że większość narzędzi jest napisana w C (a następnie skompilowana do plików binarnych), a nie bash. Dlaczego te narzędzia implementują tę funkcję?
J.Joe
@ J.Joe Ponieważ dzwonią getopt()(deklarowane w unistd.h), co robi to samo.
Kusalananda
2
Tak, masz rację. Odniesienia . To rozwiązuje również kolejną zagadkę, że opcje można łączyć -a -b=== -ab
J.Joe
1
Opcjonalne argumenty dla flag stworzyłyby niejednoznaczność, więc nie można ich łączyć (jeśli -ama opcjonalny argument, -abto nie to samo, co -a -b). GNU getopt nie zatrzymuje przetwarzania flag po spotkaniu z nie-flagą: zamiast tego (domyślnie), zamiast tego przetasowuje flagi na przód argv.
ilkkachu
@ilkkachu Dzięki za wyjaśnienie. Mogę zaktualizować swoją odpowiedź później.
Kusalananda
4

xargsjest jednym z narzędzi POSIX. Jak skomentował @drewbenn, POSIX dokumentuje zachowanie parsowania opcji dla większości swoich narzędzi do dopasowania getopt, z pewnymi tolerancjami dla innych implementacji, mówiąc w 12.1 Składnia argumentu narzędzia :

Ta sekcja opisuje składnię argumentów standardowych narzędzi i wprowadza terminologię stosowaną w POSIX.1-2008 do opisywania argumentów przetwarzanych przez narzędzia.

W POSIX.1-2008 do opisu składni argumentów narzędzia używana jest specjalna notacja. O ile nie zaznaczono inaczej , wszystkie opisy programów narzędziowych używają tej notacji, którą ilustruje ten przykład (patrz Proste polecenia XCU ):

i kończąc z

Zaleca się, aby wszystkie przyszłe narzędzia i aplikacje korzystały z tych wytycznych w celu zwiększenia przenośności użytkownika. Fakt, że niektórych historycznych narzędzi nie można było zmienić (aby uniknąć zepsucia istniejących aplikacji), nie powinien powstrzymywać tego przyszłego celu.

W POSIX (pamiętaj, że obejmuje on tylko najczęściej używane narzędzia), istnieją wyjątki, które przekazują operandy, które byłyby opcjami w innych narzędziach jako parametry pozycyjne lub parametry o specjalnej składni :

POSIX pozwala na opcjonalne wartości opcji:

Argumenty opcji są oddzielone od ich opcji <blank>znakami, z wyjątkiem sytuacji, gdy argument-opcji jest ujęty w notacji '['i ']'oznacza, że ​​jest opcjonalny.

Nie pamiętam, które narzędzia POSIX używają tej funkcji. Ncurses tici infocmpnarzędzia używają tej funkcji dla poziomów opcji -v(pełne / debugowanie).

Konkretny punkt, o który pytałeś, jest szczegółowo opisany w pozostałej części tego akapitu, w kilku wierszach.

Przed POSIX-em niektóre implementacje pszaakceptowanych opcji bez łącznika wiodącego. Opis POSIX nie wspomina o tym w opisie narzędzia ani w uzasadnieniu składni:

Oprócz POSIX istnieją implementacje długich opcji (takie jak GNU getopt_long lub X Toolkit ), wykorzystujące różne sposoby oddzielania lub łączenia wartości opcji z opcją. Na przykład można zastosować interpunkcję:

--option=value
--option value

W zależności od implementacji podwójny myślnik może / nie może być użyty do odróżnienia długich opcji od krótkich (getopt): Lynx i X Toolkit używają pojedynczego myślnika; Na przykład GNU getopt_longużywa podwójnego myślnika. Można również +użyć a, aby wskazać, że opcja jest zanegowana.

Opis POSIX nie wydaje się wymieniać żadnego z nich, ale na pewno je spotkasz.

Thomas Dickey
źródło
Czy -option=valuema być --option=value? (Format długiej opcji, dwa myślniki na początku zamiast jednego)
J.Joe
Kilka starszych narzędzi korzysta z długich opcji pojedynczego myślnika (-opcja), ale są one w dużej mierze przestarzałe dla nowych skryptów i programów. Użyj pojedynczego myślnika dla krótkich opcji obsługiwanych przez getopt. Prawie wszystkie nowe skrypty i programy używają opcji podwójnego kreskowania. Wiele obsługuje również ekwiwalenty krótkich opcji pojedynczego myślnika dla najczęściej używanych. Długie opcje sprawiają, że kod skryptu jest znacznie bardziej samodokumentujący, wymagający mniej komentarzy.
DocSalvager,