Kuinka käyttää getoptia bash-komentorivillä vain pitkillä vaihtoehdoilla?

Bash-komentorivillä on getopt -komento. getopt voidaan käyttää lyhyillä vaihtoehdoilla (kuten getopt -o axby "$@"), ja sitä voidaan käyttää sekä lyhyiden että pitkien vaihtoehtojen kanssa (kuten getopt -o axby -l long-key -- "$@"), mutta nyt tarvitsen vain pitkiä vaihtoehtoja (ts. lyhyitä vaihtoehtoja ei ole ollenkaan), mutta komento getopt -l long-key -- "$@" doesn ”t jäsentää --long-key -vaihtoehdon oikein. Joten miten voin käyttää komentoa getopt vain pitkillä vaihtoehdoilla? Vai onko se mahdotonta, vai onko se vain vika getopt -komennossa?

Kommentit

  • Sinä sisäisen getopts -tunnisteen, mutta käytät komentoa /usr/bin/getopt.
  • @Anthon Valitettavasti olen käyttänyt väärä tunniste, mutta en ole ' saanut riittävästi mainetta lisätäksesi uuden tunnisteen, joka tarvitsee 300 mainetta. Olen kuitenkin poistanut väärän tunnisteen juuri nyt.

Vastaa

getopt on täysin hieno ilman lyhyitä vaihtoehtoja. Mutta sinun on kerrottava sille, että sinulla ei ole lyhyitä vaihtoehtoja. Se on omituinen syntaksissa – käsikirjasta:

Jos ei -o tai --options -vaihtoehto löytyy ensimmäisestä osasta, toisen osan ensimmäistä parametria käytetään lyhyenä vaihtoehtojen merkkijonona.

Sitä mitä testissä tapahtuu: getopt -l long-key -- --long-key foo käsittelee --long-key vaihtoehtoluettelona -egklnoy ja foo ainoana argumenttina. Käytä

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

esim.

$ 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" 

Kommentit

  • Sekoittiko OP ' sekoittamalla getopts ja getopt tartuttaa vastauksesi? Aloitat kommentoinnilla getopts ja mainitset sitten vain getopt.
  • @Anthon Kaikki vastaukseni koskee getopt -ohjelmaa GNU coreutilsista, mistä kysymys onkin. I ve korjattu teksti, joka sanoi getopts. Kiitos. getopts ei ' edes tee pitkiä vaihtoehtoja, joten mikään näistä ei koske getopts .
  • OP: lla oli alun perin getopts -tunniste. En halunnut muuttaa vastaustasi, koska tiedät yleensä paljon paremmin kuin minä, mistä kirjoitat 🙂
  • Menetin melkein tunnin yrittäessäni selvittää tämän. Säästit vain muutaman turhaan kahvia. Kiitos … antaa tämän kahvin käyttää paremmin. ☕️

Vastaa

Älä tiedä getopt -kohdasta, mutta getopts sisäänrakennettua voidaan käyttää vain tällaisten pitkien vaihtoehtojen käsittelemiseen:

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

Tietysti, kuten ei, niin ei ” Ei toimi, jos pitkillä vaihtoehdoilla oletetaan olevan argumentteja. Se voidaan kuitenkin tehdä, mutta kuten olen oppinut työskentelemään tämän kanssa. Vaikka sisällytin sen alun perin tähän, huomasin, että pitkillä vaihtoehdoilla sillä ei ole paljon hyötyä. Tässä tapauksessa se vain lyhensi case (match) -kentät yhdellä, ennakoitavalla merkillä. Tiedän nyt, että se sopii erinomaisesti lyhyille vaihtoehdoille – se on hyödyllisin, kun se silmukkaa tuntemattoman pituisen merkkijonon yli ja valitsee yksittäisiä tavuja option-merkkijonon mukaan . Mutta kun vaihtoehto on arg, ei ole paljon tekemistä for var do case $var in -yhdistelmällä, jonka se voisi tehdä. On parempi, Luulen, että yksinkertaisuus.

Epäilen, että sama pätee getopt, mutta en tiedä siitä tarpeeksi sanoa varmuudella. Seuraavan arg-taulukon perusteella esitän oman pienen arg-jäsentimen – joka riippuu ensisijaisesti arviointi / määrityssuhteesta, jota olen arvostanut alias ja $((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 

Se on arg-merkkijono, jonka kanssa työskentelen. Nyt:

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 

Se käsittelee arg-taulukon kahdella eri tavalla riippuen siitä, annatko sille yhden vai kaksi argumenttisarjaa, jotka on erotettu -- -erottimella. Molemmissa tapauksissa se koskee arg-taulukon käsittelysekvenssejä.

Jos kutsutaan sitä näin:

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

Sen ensimmäinen järjestys Yrityksen on kirjoitettava acase() -funktionsa näyttämään tältä:

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

Ja vieressä shift 3.Komennon korvaaminen funktion acase() määritelmässä arvioidaan, kun kutsuva kuori rakentaa funktion syötteen tähän-dokumentit, mutta acase() on ei koskaan kutsuttu tai määritelty kutsuvassa kuoressa. Sitä kutsutaan tietysti alikuoressa, joten tällä tavalla voit määrittää dynaamisesti kiinnostavat vaihtoehdot komentorivillä.

Jos annat sille rajoittamaton taulukko se vain täyttää acase() vastaavuudet kaikille argumenteille, jotka alkavat merkkijonolla --.

Funktio tekee käytännössä kaiken prosessoinnin alikuoressa – säästää iteratiivisesti kutakin argin arvoa aliaksiksi, jotka liitetään assosiatiivisiin nimiin. Kun se on läpi, tulostaa kaikki arvot, jotka se on tallentanut tiedostolla alias – joka on POSIX-määritelty tulostamaan kaikki mainitut tallennetut arvot siten, että niiden arvot voidaan palauttaa komentotulkkiin. Joten kun teen …

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

Sen tulos näyttää tältä:

...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" 

Käydessään arg-luetteloa se tarkistaa ottelun tapauslohkon. Jos se löytää ottelun, se heittää lipun – f=optname. Kunnes se löytää jälleen kelvollisen vaihtoehdon, se lisää jokaisen seuraavan argin matriisiin, jonka se rakentaa nykyisen lipun perusteella. Jos sama vaihtoehto määritetään useita kertoja, tulosyhdistelmä ei ohita. Kaikki, mitä ei ole, tai mikä tahansa argumentti, joka seuraa ohitettuja vaihtoehtoja, määritetään ohitetulle taulukolle.

Lähtö on suojattu kuorelle kuoren syöttöä varten kuoren toimesta automaattisesti. :

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

… pitäisi olla täysin turvallinen. Jos se jostain syystä ei ole turvallinen, sinun on todennäköisesti toimitettava virheraportti kuoren ylläpitäjälle.

Se määrittää kahden tyyppisen aliaksen arvon kullekin ottelulle. Ensinnäkin se asettaa lipun – tämä tapahtuu riippumatta siitä, onko vaihtoehto edeltävä argumentteja, jotka eivät täsmää. Joten mikä tahansa --flag: n esiintyminen arg-luettelossa laukaisee flag=1. Tämä ei muodosta yhdistelmää – --flag --flag --flag saa vain flag=1. Tämä arvo lisää kuitenkin kasvua – kaikille argumenteille, jotka saattavat seurata sitä. Sitä voidaan käyttää hakemistoavaimena. Suoritettuani yllä olevan eval -kohdan voin:

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

… saada …

8 1 

Ja niin:

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 

Ja argumentteihin, jotka eivät vastanneet, korvaan ohitettu yllä olevassa for ... in -kentässä saadaksesi:

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 

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *