Ich möchte, dass lange und kurze Formen von Befehlszeilenoptionen mit meinem Shell-Skript aufgerufen werden.
Ich weiß, dass das getopts
verwendet werden kann, aber wie in Perl war ich nicht in der Lage, dasselbe mit Shell zu tun.
Irgendwelche Ideen, wie dies gemacht werden kann, damit ich Optionen verwenden kann wie:
./shell.sh --copyfile abc.pl /tmp/
./shell.sh -c abc.pl /tmp/
Oben bedeuten beide Befehle dasselbe für meine Shell, aber mit getopts
konnte ich diese nicht implementieren?
bash
command-line-arguments
getopt
getopts
gagneet
quelle
quelle
Antworten:
Es gibt drei Implementierungen, die in Betracht gezogen werden können:
Bash eingebaut
getopts
. Dies unterstützt keine langen Optionsnamen mit dem Doppelstrichpräfix. Es werden nur Einzelzeichenoptionen unterstützt.BSD UNIX-Implementierung eines eigenständigen
getopt
Befehls (der von MacOS verwendet wird). Dies unterstützt auch keine langen Optionen.GNU-Implementierung von Standalone
getopt
. GNUgetopt(3)
(wird von der Befehlszeilegetopt(1)
unter Linux verwendet) unterstützt das Parsen langer Optionen.Einige andere Antworten zeigen eine Lösung für die Verwendung der eingebauten Bash
getopts
, um lange Optionen nachzuahmen. Diese Lösung macht tatsächlich eine kurze Option, deren Charakter "-" ist. Sie erhalten also "-" als Flagge. Dann wird alles, was folgt, zu OPTARG, und Sie testen das OPTARG mit einem verschachteltencase
.Das ist klug, bringt aber einige Einschränkungen mit sich:
getopts
kann die opt-Spezifikation nicht erzwingen. Es können keine Fehler zurückgegeben werden, wenn der Benutzer eine ungültige Option angibt. Sie müssen Ihre eigene Fehlerprüfung durchführen, während Sie OPTARG analysieren.Während es möglich ist, mehr Code zu schreiben, um die mangelnde Unterstützung für lange Optionen zu umgehen, ist dies viel mehr Arbeit und macht den Zweck der Verwendung eines getopt-Parsers zur Vereinfachung Ihres Codes teilweise zunichte.
quelle
getopt
undgetopts
sind verschiedene Tiere, und die Leute scheinen ein bisschen Missverständnis darüber zu haben, was sie tun.getopts
ist ein integrierter Befehl zumbash
Verarbeiten von Befehlszeilenoptionen in einer Schleife und zum Zuweisen jeder gefundenen Option und jedes gefundenen Werts zu integrierten Variablen, damit Sie sie weiter verarbeiten können.getopt
Es handelt sich jedoch um ein externes Dienstprogramm, das Ihre Optionen für Sie nicht so verarbeitet, wie es beispielsweise Bashgetopts
, das Perl-Getopt
Modul oder Pythonoptparse
/argparse
Module tun. Alles,getopt
was Sie tun müssen, ist, die übergebenen Optionen zu kanonisieren - dh sie in ein Standardformular zu konvertieren, damit ein Shell-Skript sie leichter verarbeiten kann. Beispielsweise kann eine Anwendung vongetopt
Folgendes konvertieren:das sehr gut finden:
Sie müssen die eigentliche Bearbeitung selbst vornehmen. Sie müssen überhaupt nicht verwenden,
getopt
wenn Sie verschiedene Einschränkungen für die Angabe von Optionen vornehmen:-o
oben) muss der Wert als separates Argument (nach einem Leerzeichen) angegeben werden.Warum
getopt
statt verwendengetopts
? Der Hauptgrund ist, dass nur GNUgetopt
Ihnen Unterstützung für lange benannte Befehlszeilenoptionen bietet. 1 (GNUgetopt
ist die Standardeinstellung unter Linux. Mac OS X und FreeBSD werden mit einer einfachen und nicht sehr nützlichen Version geliefertgetopt
Version , aber die GNU-Version kann installiert werden. Siehe unten.)Hier ist zum Beispiel ein Beispiel für die Verwendung von GNU
getopt
aus einem meiner Skripte mit dem Namenjavawrap
:Auf diese Weise können Sie Optionen wie
--verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"
oder ähnlich angeben . Der Aufruf vongetopt
besteht darin, die Optionen zu kanonisieren,--verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"
damit Sie sie einfacher verarbeiten können. Das Zitieren um"$1"
und"$2"
ist wichtig, da es sicherstellt, dass Argumente mit Leerzeichen richtig behandelt werden.Wenn Sie die ersten 9 Zeilen löschen (alles durch die
eval set
Zeile), funktioniert der Code weiterhin ! Ihr Code ist jedoch viel wählerischer in Bezug auf die Arten von Optionen, die er akzeptiert: Insbesondere müssen Sie alle Optionen in der oben beschriebenen "kanonischen" Form angeben. Mit der Verwendung vongetopt
können Sie jedoch Einzelbuchstabenoptionen gruppieren, kürzere, nicht mehrdeutige Formen von Langoptionen verwenden, entweder den--file foo.txt
oder--file=foo.txt
-Stil verwenden, entweder den-m 4096
oder-m4096
-Stil verwenden, Optionen und Nichtoptionen in beliebiger Reihenfolge mischen usw.getopt
gibt auch eine Fehlermeldung aus, wenn nicht erkannte oder mehrdeutige Optionen gefunden werden.HINWEIS : Es gibt tatsächlich zwei völlig unterschiedliche Versionen von
getopt
Basicgetopt
und GNUgetopt
mit unterschiedlichen Funktionen und unterschiedlichen Anrufkonventionen. 2 Basicgetopt
ist ziemlich kaputt: Es verarbeitet nicht nur keine langen Optionen, sondern auch nicht einmal eingebettete Leerzeichen innerhalb von Argumenten oder leeren Argumenten, wohingegengetopts
dies richtig ist. Der obige Code funktioniert nicht in Basicgetopt
. GNUgetopt
wird standardmäßig unter Linux installiert, muss jedoch unter Mac OS X und FreeBSD separat installiert werden. Installieren Sie unter Mac OS X MacPorts ( http://www.macports.org ) undsudo port install getopt
installieren Sie dann GNUgetopt
(normalerweise in/opt/local/bin
) und stellen Sie sicher, dass/opt/local/bin
sich das in Ihrem Shell-Pfad befindet/usr/bin
. Installieren Sie unter FreeBSDmisc/getopt
.Eine Kurzanleitung zum Ändern des Beispielcodes für Ihr eigenes Programm: Von den ersten Zeilen ist alles "Boilerplate", das bis auf die aufrufende Zeile gleich bleiben sollte
getopt
. Sie sollten den Programmnamen nach ändern-n
, kurze Optionen nach-o
und lange Optionen nach angeben--long
. Setzen Sie nach Optionen, die einen Wert annehmen, einen Doppelpunkt.Wenn Sie schließlich Code sehen, der nur
set
anstelle von hateval set
, wurde er für BSD geschriebengetopt
. Sie sollten es ändern, um deneval set
Stil zu verwenden, der mit beiden Versionen von gut funktioniertgetopt
, während die Ebeneset
mit GNU nicht richtig funktioniertgetopt
.1 Eigentlich
getopts
inksh93
Trägern lange genannte Optionen, aber diese Schale nicht so oft verwendetbash
. Inzsh
Verwenden Siezparseopts
diese Funktionalität zu erhalten.2 Technisch gesehen ist "GNU
getopt
" eine Fehlbezeichnung. Diese Version wurde eher für Linux als für das GNU-Projekt geschrieben. Es folgt jedoch allen GNU-Konventionen, und der Begriff "GNUgetopt
" wird häufig verwendet (z. B. bei FreeBSD).quelle
getopt
unter Linux ist kein GNU-Dienstprogramm und das traditionellegetopt
kommt ursprünglich nicht von BSD, sondern von AT & T Unix. ksh93sgetopts
(ebenfalls von AT & T) unterstützen lange Optionen im GNU-Stil.POSIXLY_CORRECT
verhält (z. B. unter Verwendung von ), während "Linux-erweitertes getopt" fälschlicherweise darauf hinweist, dass diese Version nur auf existiert Linux.getopt
leicht auf andere Unices portiert werden könnte, aber viele andere Softwareprodukteutil-linux
sind Linux-spezifisch). Alle Nicht-GNU-Programme, die GNU getopt (3) verwenden, verstehen$POSIX_CORRECT
. Zum Beispiel würden Sie nicht sagen, dass diesaplay
nur aus diesen Gründen GNU ist. Ich vermute, wenn FreeBSD GNU getopt erwähnt, bedeutet dies die GNU getopt (3) C-API.getopt
util bezieht , nicht auf getopt (3).Mit der in Bash integrierten Funktion getopts können Sie lange Optionen analysieren, indem Sie ein Bindestrichzeichen gefolgt von einem Doppelpunkt in die Option optspec einfügen:
Nach dem Kopieren in den ausführbaren Dateinamen =
getopts_test.sh
im aktuellen Arbeitsverzeichnis kann eine Ausgabe wie erzeugt werdenOffensichtlich führt getopts weder eine
OPTERR
Überprüfung noch eine Analyse von Optionsargumenten für die langen Optionen durch. Das obige Skriptfragment zeigt, wie dies manuell erfolgen kann. Das Grundprinzip funktioniert auch in der Debian Almquist-Shell ("dash"). Beachten Sie den Sonderfall:Beachten Sie, dass als GreyCat von über an dieser Trick http://mywiki.wooledge.org/BashFAQ , ein nicht standardmäßiges Verhalten der Shell ausnutzt, das das Optionsargument zulässt (dh den Dateinamen in "-f Dateiname"). mit der Option verkettet werden (wie in "-ffilename"). Der POSIX- Standard besagt, dass zwischen ihnen ein Leerzeichen stehen muss, was im Fall von "- longoption" die Optionsanalyse beenden und alle longoptions in Nichtoptionsargumente verwandeln würde.
quelle
!
inval="${!OPTIND}
?getopts
automatisch nurOPTIND
mit 1 erhöht , aber in unserem Fall muss es um 2 erhöht werden, also erhöhen wir es manuell um 1 und lassengetopts
es dann für uns automatisch wieder um 1 erhöhen.$
erforderlich.OPTIND=$(( $OPTIND + 1 ))
kann gerecht seinOPTIND=$(( OPTIND + 1 ))
. Noch interessanter ist, dass Sie Variablen innerhalb eines arithmetischen Ausdrucks sogar zuweisen und erhöhen können, sodass Sie ihn weiter abkürzen: $(( ++OPTIND ))
oder sogar(( ++OPTIND ))
berücksichtigen können, dass er++OPTIND
immer positiv ist, sodass ein Shell-Lauf mit dieser-e
Option nicht ausgelöst wird. :-) gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html--very-bad
Warnung?Das eingebaute
getopts
Befehl AFAIK ist weiterhin nur auf Optionen mit nur einem Zeichen beschränkt.Es gibt (oder gab es früher) ein externes Programm
getopt
, das eine Reihe von Optionen so neu organisiert, dass es einfacher zu analysieren ist. Sie können dieses Design auch an lange Optionen anpassen. Anwendungsbeispiel:Sie können ein ähnliches Schema mit einem
getoptlong
Befehl verwenden.Beachten Sie, dass die grundlegende Schwäche des externen
getopt
Programms darin besteht, dass es schwierig ist, Argumente mit Leerzeichen zu behandeln und diese Leerzeichen genau beizubehalten. Aus diesem Grund ist das integriertegetopts
Gerät überlegen, obwohl es nur durch die Verwendung von Einzelbuchstabenoptionen eingeschränkt ist.quelle
eval set
mit Anführungszeichen zu verwenden (siehe meine Antwort unten), damit es auch mit GNU getopt (der Standardeinstellung unter Linux) korrekt funktioniert und Leerzeichen korrekt behandelt.${1+"$@"}
kurios ist und im Widerspruch zu dem steht, was in modernen Shells und insbesondere zu jeder Shell unter Linux erforderlich ist. Siehe Verwenden von $ 1: + "$ @"} in / bin / sh für a Diskussion dieser Notation.)eval set
es sowohl mit GNU als auch mit BSD das Richtige tutgetopt
, während Plainset
nur mit BSD das Richtige tutgetopt
. Sie können es also auch verwendeneval set
, um Menschen zu ermutigen, sich daran zu gewöhnen. Übrigens, danke, ich wusste nicht, dass${1+"$@"}
das nicht mehr gebraucht wurde. Ich muss Dinge schreiben, die sowohl unter Mac OS X als auch unter Linux funktionieren - zwischen den beiden erzwingen sie viel Portabilität. Ich habe gerade überprüft und"$@"
macht in der Tat , das Richtige auf allesh
,bash
,ksh
, undzsh
unter Mac OS X; sicherlich auch unter Linux.Hier ist ein Beispiel, das getopt mit langen Optionen verwendet:
quelle
eval set
, dass es mit Anführungszeichen verwendet wird (siehe meine Antwort unten), damit es auch mit GNU getopt (der Standardeinstellung unter Linux) korrekt funktioniert und Leerzeichen korrekt verarbeitet.getopt
während die Frage istgetopts
.(--
,(-*
und(*
gültige Muster? Wie unterscheiden sie sich von--
,-*
und*
?(--)
identisch mit--)
einercase
Zeilengruppe. Es ist seltsam, die ungleichmäßige Einrückung und inkonsistente Verwendung dieser optionalen führenden Parens zu sehen, aber der aktuelle Code der Antwort scheint mir gültig zu sein.Lange Optionen können vom
getopts
eingebauten Standard als "Argumente" für die-
"Option" analysiert werden.Dies ist eine tragbare und native POSIX-Shell - es werden keine externen Programme oder Bashismen benötigt.
Dieser Leitfaden implementiert lange Optionen als Argumente für die
-
Option, so--alpha
ist zu sehen , vongetopts
wie-
mit dem Argumentalpha
und--bravo=foo
wird als gesehen-
mit dem Argumentbravo=foo
. Das wahre Argument kann mit einem einfachen Ersatz geerntet werden :${OPTARG#*=}
.In diesem Beispiel haben
-b
und-c
(und ihre langen Formen--bravo
und--charlie
) obligatorische Argumente. Argumente für lange Optionen kommen nach Gleichheitszeichen, z. B.--bravo=foo
(Leerzeichen für lange Optionen wären schwer zu implementieren, siehe unten).Da dies die
getopts
integrierte Lösung verwendet, unterstützt diese Lösung eine Verwendung wiecmd --bravo=foo -ac FILE
(die Optionen kombiniert-a
und-c
lange Optionen mit Standardoptionen verschachtelt), während die meisten anderen Antworten hier entweder Schwierigkeiten haben oder dies nicht tun.Wenn die Option ein Bindestrich (
-
) ist, ist es eine lange Option.getopts
wird die tatsächliche lange Option in$OPTARG
zB--bravo=foo
ursprüngliche SätzeOPT='-'
und analysiert habenOPTARG='bravo=foo'
. Dieif
Zeilengruppe setzt$OPT
auf den Inhalt von$OPTARG
vor dem ersten Gleichheitszeichen (bravo
in unserem Beispiel) und entfernt dieses am Anfang von$OPTARG
(ergibt=foo
in diesem Schritt oder eine leere Zeichenfolge, wenn keine vorhanden ist=
). Schließlich streifen wir die Argumentation ab=
. Zu diesem Zeitpunkt$OPT
ist entweder eine kurze Option (ein Zeichen) oder eine lange Option (2+ Zeichen).Das entspricht
case
dann entweder kurzen oder langen Optionen.getopts
Beschwert sich bei kurzen Optionen automatisch über Optionen und fehlende Argumente, sodass wir diese manuell mithilfe von replizieren müssenneeds_arg
Funktion , die tödlich beendet wird, wenn sie$OPTARG
leer ist. Die??*
Bedingung?
stimmt mit jeder verbleibenden langen Option überein ( entspricht einem einzelnen Zeichen und*
entspricht null oder mehr, entspricht also??*
2+ Zeichen), sodass wir vor dem Beenden den Fehler "Unzulässige Option" ausgeben können.(Ein Hinweis zu Variablennamen in Großbuchstaben: Im Allgemeinen wird empfohlen, Variablen in Großbuchstaben für die Systemnutzung zu reservieren. Ich
$OPT
behalte sie in Großbuchstaben, um sie im Einklang zu halten$OPTARG
, aber dies verstößt gegen diese Konvention. Ich denke, es passt, weil dies etwas ist, was das System hätte tun sollen, und es sollte sicher sein, weil es keine Standards (afaik) gibt, die eine solche Variable verwenden.)Um sich über unerwartete Argumente für lange Optionen zu beschweren, ahmen Sie nach, was wir für obligatorische Argumente getan haben: Verwenden Sie eine Hilfsfunktion. Drehen Sie den Test einfach um, um sich über ein Argument zu beschweren, wenn eines nicht erwartet wird:
Ein ältere Version dieser Antwort hatte den Versuch, lange Optionen mit durch Leerzeichen getrennten Argumenten zu akzeptieren, war jedoch nicht zuverlässig.
getopts
könnte vorzeitig beendet werden, wenn angenommen wird, dass das Argument außerhalb seines Geltungsbereichs liegt und das manuelle Inkrementieren$OPTIND
nicht in allen Shells funktioniert.Dies würde unter Verwendung einer dieser Techniken erreicht werden:
eval "bravo=\"\$$OPTIND\""
bravo="${!OPTIND}"
P
Flag :bravo="${(P)OPTIND}"
und schloss dann mit so etwas
[ $# -gt $OPTIND ] && OPTIND=$((OPTIND+1))
quelle
letter-c
kein Argument braucht, würde es nicht ausreichen, es zu verwendenletter-c)
? das*
scheint überflüssig.getopts
stoppt beim ersten Positionsargument, da es nicht dafür ausgelegt ist, mit ihnen umzugehen. Dies ermöglicht Unterbefehle mit eigenen Argumenten, z. B.git diff --color
würdecommand --foo=moo bar --baz waz
ich--foo
als Argument fürcommand
und--baz waz
als Argument (mit Option) für denbar
Unterbefehl interpretieren . Dies kann mit dem obigen Code erfolgen. Ich lehne ab,--bravo -blah
weil--bravo
ein Argument erforderlich ist und es unklar ist, dass dies-blah
keine andere Option ist.eval
in der POSIX-Shell erforderlich ist , wird es unter dem Rest der Antwort aufgeführt.Schauen Sie sich shFlags an , eine tragbare Shell-Bibliothek (dh: sh, bash, dash, ksh, zsh unter Linux, Solaris usw.).
Das Hinzufügen neuer Flags ist so einfach wie das Hinzufügen einer Zeile zu Ihrem Skript, und es bietet eine automatisch generierte Verwendungsfunktion.
Hier ist eine einfache
Hello, world!
Verwendung von shFlag :Für Betriebssysteme mit dem erweiterten getopt, das lange Optionen unterstützt (z. B. Linux), können Sie Folgendes tun:
Im Übrigen müssen Sie die kurze Option verwenden:
Das Hinzufügen eines neuen Flags ist so einfach wie das Hinzufügen eines neuen
DEFINE_ call
.quelle
Verwendung
getopts
mit kurzen / langen Optionen und ArgumentenFunktioniert mit allen Kombinationen, zB:
Einige Erklärungen für dieses Beispiel
Wie die Nutzungsfunktion aussehen würde
getops
mit langen / kurzen Flags sowie langen ArgumentenAusgabe
Kombinieren Sie das Obige zu einem zusammenhängenden Skript
quelle
eval
Ansatz für räumliche Argumente für lange Optionen gespielt und fand ihn bei bestimmten Shells unzuverlässig (obwohl ich davon ausgehe, dass er mit Bash funktioniert. In diesem Fall müssen Sie ihn nicht verwendeneval
). In meiner Antwort erfahren Sie, wie Sie lange Optionsargumente akzeptieren,=
und in meinen notierten Versuchen, Leerzeichen zu verwenden. Meine Lösung führt keine externen Anrufe durch, während diesecut
einige Male verwendet wird.Ein anderer Weg...
quelle
$args
Neuzuweisung ein Leerzeichen ? Dies könnte sogar ohne Bashismen geschehen, aber dieser Code verliert Leerzeichen in Optionen und Argumenten (ich glaube nicht, dass der$delim
Trick funktionieren wird). Sie können stattdessenset
innerhalb derfor
Schleife ausgeführt werden, wenn Sie vorsichtig genug sind, um sie nur bei der ersten Iteration zu leeren. Hier ist eine sicherere Version ohne Bashismen.Ich habe es irgendwie so gelöst:
Bin ich dumm oder so?
getopt
undgetopts
sind so verwirrend.quelle
-ltr
oder ). Darüber hinaus bietet es eine Fehlerbehandlung und eine einfache Möglichkeit, die behandelten Parameter nach Abschluss der Optionsbehandlung zu verschieben.-lt -r
-l -t -r
Wenn Sie die
getopt
Abhängigkeit nicht möchten , können Sie Folgendes tun:Dann können Sie natürlich keine langen Stiloptionen mit einem Bindestrich verwenden. Und wenn Sie verkürzte Versionen hinzufügen möchten (z. B. --verbos anstelle von --verbose), müssen Sie diese manuell hinzufügen.
Wenn Sie jedoch
getopts
Funktionalität und lange Optionen suchen , ist dies eine einfache Möglichkeit.Ich habe diesen Ausschnitt auch auf den Punkt gebracht .
quelle
--)
scheint ein zushift ;
fehlen. Im Moment--
bleibt das als erstes Argument ohne Option.--
Optionshift
dort drin sein muss . Ich sage, dies ist besser, weil die Alternativen entweder plattformabhängige Versionen von sindgetopt
odergetopts_long
Sie die Verwendung von Kurzoptionen erst zu Beginn des Befehls erzwingen müssen (dh Sie verwendengetopts
dann lange Optionen und verarbeiten sie anschließend), während dies eine beliebige Reihenfolge ergibt und vollständige Kontrolle.Der eingebaute
getopts
kann das nicht. Es gibt ein externes getopt (1) -Programm, das dies kann, aber Sie erhalten es nur unter Linux aus dem util-linux- Paket. Es wird mit einem Beispielskript getopt-parse.bash geliefert .Es gibt auch eine
getopts_long
als Shell geschriebene Funktion.quelle
getopt
wurde 1993 in FreeBSD Version 1.0 aufgenommen und ist seitdem Teil von FreeBSD. Als solches wurde es aus FreeBSD 4.x übernommen, um in das Darwin-Projekt von Apple aufgenommen zu werden. Ab OS X 10.6.8 bleibt die von Apple enthaltene Manpage ein genaues Duplikat der FreeBSD-Manpage. Also ja, es ist in OS X und Gobs anderer Betriebssysteme neben Linux enthalten. -1 zu dieser Antwort für die Fehlinformation..
quelle
"${1:0:1}"
für Argument Nr. 1, Teilzeichenfolge bei Index 0, Länge 1, stehen. Dies erlaubt kein Mischen von kurzen und langen Optionen.In
ksh93
,getopts
unterstützt lange Namen ...Zumindest haben die Tutorials, die ich gefunden habe, gesagt. Probieren Sie es aus und sehen Sie.
quelle
Ich schreibe nur ab und zu Shell-Skripte und falle aus der Praxis, daher ist jedes Feedback willkommen.
Bei Verwendung der von @Arvid Requate vorgeschlagenen Strategie haben wir einige Benutzerfehler festgestellt. Ein Benutzer, der vergisst, einen Wert anzugeben, wird versehentlich mit dem Namen der nächsten Option als Wert behandelt:
bewirkt, dass der Wert von "loglevel" als "--toc = TRUE" angezeigt wird. Dies kann vermieden werden.
Ich habe einige Ideen zum Überprüfen von Benutzerfehlern auf CLI unter http://mwiki.wooledge.org/BashFAQ/035 zur manuellen Analyse angepasst . Ich habe eine Fehlerprüfung in die Behandlung der Argumente "-" und "-" eingefügt.
Dann fing ich an, mit der Syntax herumzuspielen, daher sind alle Fehler hier ausschließlich meine Schuld, nicht die ursprünglichen Autoren.
Mein Ansatz hilft Benutzern, die es vorziehen, lange mit oder ohne Gleichheitszeichen einzugeben. Das heißt, es sollte dieselbe Antwort auf "--loglevel 9" haben wie "--loglevel = 9". Bei der - / space-Methode ist es nicht möglich, sicher zu wissen, ob der Benutzer ein Argument vergisst, sodass einige Vermutungen erforderlich sind.
Wenn Sie damit beginnen, gibt es einen interessanten Unterschied zwischen den Formaten "--opt = value" und "--opt value". Mit dem Gleichheitszeichen wird das Befehlszeilenargument als "opt = value" und die zu behandelnde Arbeit als String-Analyse angesehen, um am "=" zu trennen. Im Gegensatz dazu lautet der Name des Arguments bei "--opt value" "opt" und wir haben die Herausforderung, den nächsten in der Befehlszeile angegebenen Wert zu erhalten. Hier verwendete @Arvid Requate $ {! OPTIND}, die indirekte Referenz. Ich verstehe das immer noch überhaupt nicht und Kommentare in BashFAQ scheinen vor diesem Stil zu warnen ( http://mywiki.wooledge.org/BashFAQ/006 ). Übrigens denke ich nicht, dass die Kommentare des vorherigen Posters zur Wichtigkeit von OPTIND = $ (($ OPTIND + 1)) korrekt sind. Ich will sagen,
In der neuesten Version dieses Skripts bedeutet Flag -v VERBOSE-Ausdruck.
Speichern Sie es in einer Datei mit dem Namen "cli-5.sh", machen Sie es ausführbar, und alles funktioniert oder schlägt auf die gewünschte Weise fehl
Hier ist eine Beispielausgabe der Fehlerprüfung auf dem Benutzer intpu
Sie sollten in Betracht ziehen, -v einzuschalten, da hier Interna von OPTIND und OPTARG gedruckt werden
quelle
OPTIND=$(( $OPTIND + 1 ))
: wird benötigt, wenn Sie den Parameter von OPTIND 'verschlingen' (zum Beispiel: wenn einer verwendet wird--toc value
: Wert in der Parameternummer $ OPTIND. Sobald Sie ihn für den Wert von toc abgerufen haben, sollten Sie getopts mitteilen, dass der nächste zu analysierende Parameter kein Wert ist. aber das danach (daher das:.OPTIND=$(( $OPTIND + 1 ))
und Ihr Skript (sowie das Skript, auf das Sie sich beziehen) fehlt nach dem erledigt:shift $(( $OPTIND -1 ))
(da getopts nach dem Parsen der Parameter 1 bis OPTIND-1 beendet wurden, müssen Sie sie so verschieben$@
ist jetzt alle verbleibenden "Nicht-Optionen" -ParameterEine weitere Version des Rades erfinden ...
Diese Funktion ist ein (hoffentlich) POSIX-kompatibler einfacher Bourne-Shell-Ersatz für GNU getopt. Es unterstützt kurze / lange Optionen, die obligatorische / optionale / keine Argumente akzeptieren können, und die Art und Weise, wie Optionen angegeben werden, ist fast identisch mit GNU getopt, sodass die Konvertierung trivial ist.
Natürlich ist dies immer noch ein beträchtlicher Teil des Codes, der in ein Skript eingefügt werden muss, aber es ist ungefähr die Hälfte der Zeilen der bekannten Shell-Funktion getopt_long und möglicherweise in Fällen vorzuziehen, in denen Sie nur vorhandene GNU-getopt-Verwendungen ersetzen möchten.
Dies ist ein ziemlich neuer Code, also YMMV (und lassen Sie mich auf jeden Fall wissen, ob dies aus irgendeinem Grund nicht POSIX-kompatibel ist - Portabilität war von Anfang an beabsichtigt, aber ich habe keine nützliche POSIX-Testumgebung).
Die Verwendung von Code und Beispielen folgt:
Anwendungsbeispiel:
quelle
Die akzeptierte Antwort macht einen sehr guten Job und weist auf alle Mängel der eingebauten Bash hin
getopts
. Die Antwort endet mit:Und obwohl ich dieser Aussage im Prinzip zustimme, bin ich der Meinung, dass die Häufigkeit, mit der wir alle diese Funktion in verschiedenen Skripten implementiert haben, es rechtfertigt, ein wenig Aufwand in die Erstellung einer "standardisierten", gut getesteten Lösung zu investieren.
Als solches habe ich die integrierte Bash "aktualisiert",
getopts
indem ich siegetopts_long
in einer reinen Bash ohne externe Abhängigkeiten implementiert habe . Die Verwendung der Funktion ist 100% kompatibel mit der eingebautengetopts
.Durch Einfügen
getopts_long
(das auf GitHub gehostet wird ) in ein Skript kann die Antwort auf die ursprüngliche Frage so einfach implementiert werden wie:quelle
Ich habe noch nicht genug Repräsentanten, um seine Lösung zu kommentieren oder abzustimmen, aber die Antwort von sme hat für mich sehr gut funktioniert. Das einzige Problem, auf das ich stieß, war, dass die Argumente in einfache Anführungszeichen gesetzt wurden (also habe ich sie entfernt).
Ich habe auch einige Beispielverwendungen und Hilfetext hinzugefügt. Ich werde meine leicht erweiterte Version hier einfügen:
quelle
Hier finden Sie einige verschiedene Ansätze für das Parsen komplexer Optionen in Bash: http://mywiki.wooledge.org/ComplexOptionParsing
Ich habe das folgende erstellt, und ich denke, es ist gut, weil es nur minimalen Code enthält und sowohl lange als auch kurze Optionen funktionieren. Eine lange Option kann bei diesem Ansatz auch mehrere Argumente haben.
quelle
Ich habe ziemlich lange an diesem Thema gearbeitet ... und meine eigene Bibliothek erstellt, die Sie in Ihrem Hauptskript finden müssen. Ein Beispiel finden Sie unter libopt4shell und cd2mpc . Ich hoffe es hilft !
quelle
Eine verbesserte Lösung:
quelle
Vielleicht ist es einfacher, ksh zu verwenden, nur für den getopts-Teil, wenn lange Befehlszeilenoptionen benötigt werden, da dies dort einfacher möglich ist.
quelle
Ich wollte etwas ohne externe Abhängigkeiten mit strikter Bash-Unterstützung (-u), und ich brauchte es, um auch mit den älteren Bash-Versionen zu arbeiten. Dies behandelt verschiedene Arten von Parametern:
Fügen Sie einfach oben in Ihrem Skript Folgendes ein:
Und benutze es so:
quelle
Um plattformübergreifend kompatibel zu bleiben und die Abhängigkeit von externen ausführbaren Dateien zu vermeiden, habe ich Code aus einer anderen Sprache portiert.
Ich finde es sehr einfach zu bedienen, hier ein Beispiel:
Das erforderliche BASH ist etwas länger als es sein könnte, aber ich wollte vermeiden, dass ich mich auf die assoziativen Arrays von BASH 4 verlasse. Sie können dies auch direkt von http://nt4.com/bash/argparser.inc.sh herunterladen
quelle
Wenn alle Ihre langen Optionen eindeutige und übereinstimmende erste Zeichen als kurze Optionen haben, so zum Beispiel
Ist das gleiche wie
Sie können dies vor getopts verwenden, um $ args neu zu schreiben:
Danke für mtvee für die Inspiration ;-)
quelle
Wenn dies einfach der Fall ist, möchten Sie das Skript aufrufen
Dann können Sie diesen einfachsten Weg gehen, um ihn mit Hilfe von getopt und --longoptions zu erreichen
Versuchen Sie dies, hoffen Sie, dass dies nützlich ist
quelle
getopts "könnte verwendet werden", um lange Optionen zu analysieren, solange Sie nicht erwarten, dass sie Argumente enthalten ...
So geht's:
Wenn Sie versuchen, OPTIND zum Abrufen eines Parameters für die Option long zu verwenden, behandelt getopts diesen als ersten nicht optionalen Positionsparameter und beendet das Parsen anderer Parameter. In einem solchen Fall ist es besser, wenn Sie es manuell mit einer einfachen case-Anweisung behandeln.
Dies wird "immer" funktionieren:
Es ist jedoch nicht so flexibel wie getopts und Sie müssen einen Großteil des Fehlerprüfcodes selbst in den Fallinstanzen ausführen ...
Aber es ist eine Option.
quelle
Integriert
getopts
nur kurze Optionen analysieren (außer in ksh93), aber Sie können immer noch einige Skriptzeilen hinzufügen, damit getopts lange Optionen verarbeitet.Hier ist ein Teil des Codes unter http://www.uxora.com/unix/shell-script/22-handle-long-options-with-getopts
Hier ist ein Test:
Andernfalls kann Korn Shell ksh93 in letzter Zeit
getopts
natürlich lange Optionen analysieren und sogar eine Manpage gleichermaßen anzeigen. (Siehe http://www.uxora.com/unix/shell-script/20-getopts-with-man-page-and-long-options )quelle
Das integrierte OS X (BSD) getopt unterstützt keine langen Optionen, die GNU-Version jedoch :
brew install gnu-getopt
. Dann etwas Ähnliches wie :cp /usr/local/Cellar/gnu-getopt/1.1.6/bin/getopt /usr/local/bin/gnu-getopt
.quelle
EasyOptions verarbeitet kurze und lange Optionen:
quelle