Hogyan használható a getopt a bash parancssorban, csak hosszú opciókkal?

A bash parancssorban van egy getopt parancs. A getopt használható rövid opciókkal (például getopt -o axby "$@"), és használható rövid és hosszú opciókkal is (például getopt -o axby -l long-key -- "$@"), de most csak hosszú opciókra van szükségem (azaz a rövid opciók egyáltalán nem léteznek), azonban a getopt -l long-key -- "$@" nem “t értelmezi a --long-key opciót helyesen. Tehát hogyan használhatom a getopt parancsot csak hosszú opciókkal? Vagy lehetetlen, vagy csak a getopt parancs hibája?

Megjegyzések

  • Ön címke a belső getopts címkéhez, de a /usr/bin/getopt parancsot használja.
  • @Anthon Sajnálom, használtam rossz címke, de még nem kaptam ‘ elég hírnevet egy másik címke hozzáadásához, amihez 300 reputációra van szükség. Azonban most helytelen címkét töröltem.

Válasz

getopt teljesen rendben van, nincsenek rövid lehetőségek. De el kell mondanod neki, hogy nincsenek rövid lehetőségeid. Ez a szintaxisban furcsa – a kézikönyvből:

Ha nincs -o vagy --options opció megtalálható az első részben, a második rész első paramétere lesz a rövid opciós karakterlánc.

Ez történik a teszt során: getopt -l long-key -- --long-key foo a --long-key lehetőséget a -egklnoy és foo mint egyetlen érv. Használja a

getopt -o "" -l long-key -- "$@" 

pl.

$ getopt -l long-key -o "" -- --long-key foo --long-key -- "foo" $ getopt -l long-key -o "" -- --long-key --not-recognized -n foo getopt: unrecognized option "--not-recognized" getopt: invalid option -- "n" --long-key -- "foo" 

Megjegyzések

  • A ‘ OP keverését a getopts és getopt fertőz a válaszoddal? A getopts megjegyzéssel kezdi, majd csak getopt.
  • @Anthon Minden válaszom a GNU coreutils getopt programjára vonatkozik, amiről a kérdés szól. I kijavította a getopts szöveget. Köszönöm. getopts nem ‘ még hosszú opciókat sem végez, így ezek egyike sem vonatkozik a getopts .
  • Az OP eredetileg a getopts címkével rendelkezett. Nem akartam megváltoztatni a válaszodat, mert általában sokkal jobban tudod, mint én, miről írsz 🙂
  • Majdnem egy órát vesztettem, hogy ezt kitaláljam. Csak megspóroltál nekem néhány hiú kávét. Köszönöm … lehetővé teszi a kávé jobb felhasználását. ☕️

Válasz

Nem tudom, hogy getopt Az id = “4e7e0ccf4a”>

beépített csak hosszú opciók kezelésére használható, mint ez:

while getopts :-: o do case "$o$OPTARG" in (-longopt1) process ;; (-longopt2) process ;; esac; done 

Természetesen, ahogy van, ez nem ” Nem működik, ha állítólag vannak argumentumai a hosszú opcióknak. Meg lehet azonban tenni, de, amint megtanultam ezen dolgozni. Míg eredetileg ide vettem, rájöttem, hogy a hosszú opcióknál nincs sok hasznossága. Ebben az esetben csak a case (match) mezők egyetlen, kiszámítható karakterrel. Most azt tudom, hogy kiválóan alkalmas rövid opciókhoz – akkor a leghasznosabb, ha ismeretlen hosszúságú sztringre hurkol és egyetlen bájtot választ az opció-karaktersorozata szerint . De amikor a az opció az arg, akkor nem sok mindent csinálsz egy for var do case $var in kombinációval, amelyet megtehet. Jobb, Azt hiszem, hogy egyszerű legyek.

Gyanítom, hogy ugyanez vonatkozik a getopt re is, de nem tudok róla annyit, hogy minden bizonyossággal elmondhassam. A következő arg tömbre való tekintettel bemutatom a saját kis arg értelmezőmet – ami elsősorban attól az evaláció / hozzárendelés viszonytól függ, amelyet értékeltem alias és $((shell=math)).

set -- this is ignored by default --lopt1 -s "some "\"" args" here --ignored and these are ignored \ --alsoignored andthis --lopt2 "and some "`more" --lopt1 and just a few more 

Ez az arg sztring, amellyel” működni fogok. Most:

aopts() { env - sh -s -- "$@" } <<OPTCASE 3<<\OPTSCRIPT acase() case "\$a" in $(fmt=" (%s) f=%s; aset "?$(($f)):";;\n" for a do case "$a" in (--) break;; (--*[!_[:alnum:]]*) continue;; (--*) printf "$fmt" "$a" "${a#--}";; esac;done;printf "$fmt" "--*" ignored) (*) aset "" "\$a";;esac shift "$((SHIFT$$))"; f=ignored; exec <&3 OPTCASE aset() { alias "$f=$(($f${1:-=$(($f))+}1))" [ -n "${2+?}" ] && alias "${f}_$(($f))=$2"; } for a do acase; done; alias #END OPTSCRIPT 

Ez az arg tömböt kétféle módon dolgozza fel, attól függően, hogy átad-e neki egy vagy két argumentumkészletet, amelyet elválaszt a -- elválasztó. Mindkét esetben az arg tömb feldolgozásának szekvenciájára vonatkozik.

Ha így hívja:

: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@" 

Az első A vállalkozás az lesz, hogy megadja a acase() függvényt, hogy kinézzen:

acase() case "$a" in (--lopt1) f=lopt1; aset "?$(($f)):";; (--lopt2) f=lopt2; aset "?$(($f)):";; (--*) f=ignored; aset "?$(($f)):";; (*) aset "" "$a";;esac 

És a .A parancs-helyettesítést a acase() függvénydefinícióban akkor értékelik, amikor a hívó shell felépíti a függvény itt található dokumentumait, de a acase() soha nem hívták meg és nem definiálták a hívó shellben. Természetesen az alhéjban hívják meg, így így dinamikusan megadhatja a parancssorban az érdekes opciókat.

Ha átad egy tagolatlan tömb egyszerűen feltölti a acase() -et minden olyan argumentummal, amely a -- karakterlánccal kezdődik.

A függvény gyakorlatilag teljes feldolgozását az alhéjban végzi – az arg minden egyes értékét iteratív módon menti az asszociatív nevekhez rendelt álnevekhez. Ha rajta van, kinyomtatja az összes értéket, amelyet a alias paranccsal mentett el – ami POSIX-on van megadva, hogy kinyomtassa az összes idézett mentett értéket oly módon, hogy az értékeik visszaállíthatók legyenek a shellbe. Tehát amikor megteszem …

aopts --lopt1 --lopt2 -- "$@" 

A kimenete így néz ki:

...ignored... lopt1="8" lopt1_1="-s" lopt1_2="some "\"" args" lopt1_3="here" lopt1_4="and" lopt1_5="just" lopt1_6="a" lopt1_7="few" lopt1_8="more" lopt2="1" lopt2_1="and some "`more" 

Amint végigmegy az arg listán, ellenőrzi az eset blokkját. Ha talál egyezést, akkor zászlót dob – f=optname. Amíg még egyszer nem talál érvényes opciót, minden egyes következő argumentumot hozzáad egy tömbhöz, amelyet az aktuális zászló alapján épít. Ha ugyanazt az opciót többször is megadják, az eredmény összeteszi, és nem írja felül. Minden eset, amely nincs, vagy a figyelmen kívül hagyott opciókat követő argumentumok – figyelmen kívül hagyva tömbhöz vannak rendelve.

A kimenetet shell védi a shell számára, hogy a shell automatikusan beírja a shellbe, és így :

eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")" 

… tökéletesen biztonságosnak kell lennie. Ha valamilyen okból nem biztonságos, akkor valószínűleg hibajelentést kell benyújtania a shell karbantartójának.

Kétféle álnevet rendel minden mérkőzéshez. Először beállít egy zászlót – ez akkor fordul elő, hogy egy opció megelőzi-e a nem egyező argumentumokat. Tehát a --flag bármilyen előfordulása az arg listában kiváltja az flag=1 eseményt. Ez nem áll össze – --flag --flag --flag csak flag=1 lesz. Ez az érték azonban növekszik – minden érv után, amely ezt követheti. Indexkulcsként használható. A fenti eval elvégzése után megtehetem:

printf %s\\n "$lopt1" "$lopt2" 

… hogy …

8 1 

És így:

for o in lopt1 lopt2 do list= i=0; echo "$o = $(($o))" while [ "$((i=$i+1))" -le "$(($o))" ] do list="$list $o $i \"\${${o}_$i}\" " done; eval "printf "%s[%02d] = %s\n" $list"; done 

OUTPUT

lopt1 = 8 lopt1[01] = -s lopt1[02] = some " args lopt1[03] = here lopt1[04] = and lopt1[05] = just lopt1[06] = a lopt1[07] = few lopt1[08] = more lopt2 = 1 lopt2[01] = and some "`more 

És azoknak az argumentumoknak, amelyek nem egyeztek, a idetartozik t a fenti for ... in mezőben helyettesítem:

ignored = 10 ignored[01] = this ignored[02] = is ignored[03] = ignored ignored[04] = by ignored[05] = default ignored[06] = and ignored[07] = these ignored[08] = are ignored[09] = ignored ignored[10] = andthis 

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük