Wyjaśnij polecenie powłoki: shift $ (($ optind - 1))

30

Nie jestem facetem od Linuksa, ale utknąłem w skrypcie, który muszę przeczytać w moim Projekcie. Czy więc ktoś może mi pomóc w wykonywaniu tego polecenia?

shift $(($optind - 1))
Gaurav Pant
źródło
3
Jak zauważono poniżej, OPTIND musi być dużymi literami, a „$” w nawiasie jest opcjonalne.
DarkHeart,

Odpowiedzi:

49

shift $((OPTIND-1))(uwaga OPTINDjest pisana wielkimi literami) zwykle znajduje się natychmiast po getopts whilepętli. $OPTINDjest liczba znalezionych przez opcji getopts.

Jak pauljohn32 wspomina w komentarzach, mówiąc ściśle, OPTINDpodaje pozycję następnego argumentu wiersza poleceń.

Z podręcznika GNU Bash Reference :

getopts optstring name [args]

getoptsjest używany przez skrypty powłoki do analizowania parametrów pozycyjnych. optstringzawiera znaki opcji do rozpoznania; jeśli po znaku następuje dwukropek, opcja powinna zawierać argument, który powinien być od niej oddzielony spacją. Dwukropka („:”) i znaku zapytania („?”) Nie można używać jako znaków opcji. Za każdym razem, gdy jest wywoływana, getoptsumieszcza następną opcję w nazwie zmiennej powłoki, inicjując, namejeśli nie istnieje, oraz indeks następnego argumentu, który ma zostać przetworzony na zmienną OPTIND. OPTINDjest inicjowany na 1 za każdym razem, gdy wywoływana jest powłoka lub skrypt powłoki. Gdy opcja wymaga argumentu, getopts umieszcza ten argument w zmiennej OPTARG. Powłoka nie resetuje sięOPTIND automatycznie; musi zostać ręcznie zresetowany między wieloma wywołaniami w getoptsramach tego samego wywołania powłoki, jeśli ma być użyty nowy zestaw parametrów.

Po napotkaniu końca opcji następuje getoptswyjście z wartością zwracaną większą od zera. OPTINDjest ustawiony na indeks pierwszego argumentu nie będącego opcją, a nazwa jest ustawiona na „?”.

getoptsnormalnie analizuje parametry pozycyjne, ale jeśli podano więcej argumentów args, getoptsanalizuje je zamiast tego.

shift n
usuwa n ciągów z listy parametrów pozycyjnych. W ten sposób shift $((OPTIND-1))usuwa wszystkie przeanalizowane opcje getoptsz listy parametrów, a więc po tym punkcie $1będzie odnosił się do pierwszego nieopcji argumentu przekazanego do skryptu.

Aktualizacja

Jak mikeserv wspomina w komentarzu, shift $((OPTIND-1))może być niebezpieczne. Aby zapobiec niechcianemu dzieleniu słów itp., Wszystkie rozszerzenia parametrów powinny być cytowane. Tak więc bezpieczną formą polecenia jest

shift "$((OPTIND-1))"

PM 2 Ring
źródło
Wygląda na to, że zadziała to tylko wtedy, gdy wszystkie opcje pojawią się przed pozostałymi argumentami pozycyjnymi. Poprawny?
Steve Jorgensen
@ SteveJorgensen: Tak, zgadza się. OTOH, wstawianie opcji po argumentach nieopartych jest sprzeczne z konwencją sh / bash. Zasadniczo pierwsze argumenty, które nie zaczynają się od myślnika, oznaczają koniec opcji, a wszelkie kolejne argumenty rozpoczynające się od myślnika nie są uważane za opcje. Nie wszystkie programy stosują się do tej konwencji, ale ułatwia to życie. :)
PM 2, dzwonić
@SteveJorgensen: (ciąg dalszy) Ten temat jest krótko omawiany w Dlaczego niektóre narzędzia analizują operandy przed opcjami? . Jak wspomina komentarz Gillesa do odpowiedzi Celady, niektóre programy (jak find) mogą wyglądać, jakby dopuszczały opcje po braku opcji, ale nie mają: mają operandy, które zaczynają się od myślnika.
PM 2, dzwoni
Dzięki za te informacje (i edycję) @mosvy To dość niezwykłe IFS, ale lepiej być bezpiecznym niż żałować. ;)
PM 2Ring
@roaima if IFS=0123456789, shift $((OPTIND-1))(bez cudzysłowów) zmieni się w, shift ""który zostanie po cichu zignorowany (in ksh) lub wygeneruje błąd (in bashi dash).
mosvy
8

$((...))po prostu oblicza rzeczy. W twoim przypadku bierze ona wartość $optinti odejmuje 1.

shiftusuwa parametry pozycyjne. W twoim przypadku usuwa optint-1parametry.

Aby uzyskać więcej informacji zajrzyj na help getopts, help shift, spojrzenie man bashna „arytmetycznego”, a zwłaszcza google getopts.

michas
źródło