Angenommen, ich habe ein Skript, das mit dieser Zeile aufgerufen wird:
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
oder dieses:
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile
Was ist die akzeptierte Möglichkeit , diese , so dass (oder eine Kombination aus beiden) jeweils zu parsen $v
, $f
und $d
werden alle eingestellt werden true
und $outFile
gleich sein wird /fizz/someOtherFile
?
zparseopts -D -E -M -- d=debug -debug=d
Und beide-d
und--debug
im$debug
Arrayecho $+debug[1]
geben 0 oder 1 zurück, wenn eine davon verwendet wird. Ref: zsh.org/mla/users/2011/msg00350.htmlAntworten:
Methode 1: Verwenden von bash ohne getopt [s]
Zwei gebräuchliche Methoden zum Übergeben von Schlüssel-Wert-Paar-Argumenten sind:
Bash Space-Separated (zB
--option argument
) (ohne getopt [s])Verwendungszweck
demo-space-separated.sh -e conf -s /etc -l /usr/lib /etc/hosts
Ausgabe vom Einfügen des obigen Blocks:
Bash Equals-Separated (zB
--option=argument
) (ohne getopt [s])Verwendungszweck
demo-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts
Ausgabe vom Einfügen des obigen Blocks:
Zum besseren Verständnis
${i#*=}
suchen Sie in diesem Handbuch nach "Entfernen von Teilzeichenfolgen" . Es ist funktional äquivalent zu`sed 's/[^=]*=//' <<< "$i"`
dem , was einen unnötigen Unterprozess`echo "$i" | sed 's/[^=]*=//'`
aufruft oder der zwei unnötige Unterprozesse aufruft .Methode 2: Bash mit getopt [s] verwenden
von: http://mywiki.wooledge.org/BashFAQ/035#getopts
Einschränkungen für getopt (1) (ältere, relativ aktuelle
getopt
Versionen):Neuere
getopt
Versionen haben diese Einschränkungen nicht.Darüber hinaus bietet die POSIX-Shell (und andere)
getopts
diese Einschränkungen nicht an. Ich habe ein vereinfachtesgetopts
Beispiel beigefügt .Verwendungszweck
demo-getopts.sh -vf /etc/hosts foo bar
Ausgabe vom Einfügen des obigen Blocks:
Die Vorteile von
getopts
sind:dash
.-vf filename
automatisch mehrere einzelne Optionen wie auf typische Unix-Weise verarbeiten.Der Nachteil von
getopts
ist, dass es nur kurze Optionen (-h
nicht--help
) ohne zusätzlichen Code verarbeiten kann.Es gibt ein getopts-Tutorial, in dem erklärt wird, was alle Syntax und Variablen bedeuten. In Bash gibt es auch
help getopts
, was informativ sein könnte.quelle
getopt
die alle Funktionen vongetopts
und noch einige mehr enthält.man getopt
Unter Ubuntu 13.04 wirdgetopt - parse command options (enhanced)
der Name ausgegeben, daher gehe ich davon aus, dass diese erweiterte Version jetzt Standard ist.getopt
ist kein GNU-Dienstprogramm, es ist Teil vonutil-linux
.-gt 0
, entfernen Sie Ihreshift
nach demesac
, erweitern Sie alleshift
um 1 und fügen Sie diesen Fall hinzu:*) break;;
Sie können nicht optionale Argumente verarbeiten. Beispiel: pastebin.com/6DJ57HTc–default
. Im ersten Beispiel–default
while [[ $# -gt 1 ]]
while [[ $# -gt 0 ]]
Keine Antwort erwähnt verbesserte getopt . Und die Antwort mit der höchsten Bewertung ist irreführend: Sie ignoriert entweder
-vfd
Stil-Kurzoptionen (vom OP angefordert) oder Optionen nach Positionsargumenten (auch vom OP angefordert). und es ignoriert Parsing-Fehler. Stattdessen:getopt
von Util-Linux oder früher GNU Glibc . 1getopt_long()
der C-Funktion von GNU glibc.getopt
kann dies nicht)script.sh -o outFile file1 file2 -v
(getopts
tut dies nicht)=
-style lange Optionen:script.sh --outfile=fileOut --infile fileIn
(beide zuzulassen ist langwierig, wenn sie selbst analysiert werden)-vfd
(echte Arbeit, wenn selbst analysiert)-oOutfile
oder-vfdoOutfile
getopt --test
→ Rückgabewert 4.getopt
oder Shell-eingebautegetopts
sind von begrenztem Nutzen.Die folgenden Aufrufe
Alle kehren zurück
mit den folgenden
myscript
1 erweitertes getopt ist auf den meisten "Bash-Systemen" verfügbar, einschließlich Cygwin; Unter OS X versuchen Sie, Brew Gnu-Getopt oder
sudo port install getopt
2 zu installieren. Die POSIX-
exec()
Konventionen haben keine zuverlässige Möglichkeit, binäres NULL in Befehlszeilenargumenten zu übergeben. Diese Bytes beenden vorzeitig dieerste Version vonArgument3, die 1997 oder früher veröffentlicht wurde (ich habe sie nur bis 1997 zurückverfolgt).
quelle
getopt
ist der richtige Weg.getopt
besteht, dass es nicht bequem in Wrapper-Skripten verwendet werden kann, in denen möglicherweise nur wenige Optionen für das Wrapper-Skript verfügbar sind, und dann die Nicht-Wrapper-Skript-Optionen an die umschlossene ausführbare Datei intakt übergeben werden. Nehmen wir an, ich habe einengrep
Wrapper namensmygrep
und ich habe eine--foo
spezifische Option fürmygrep
, dann kann ich das nichtmygrep --foo -A 2
und habe die-A 2
automatisch an übergebengrep
. Ich brauche zu tunmygrep --foo -- -A 2
. Hier ist meine Implementierung zusätzlich zu Ihrer Lösung.man bash
Prägnanter Weg
script.sh
Verwendungszweck:
quelle
while [[ "$#" > 1 ]]
wenn ich das Beenden der Zeile mit einem booleschen Flag unterstützen möchte./script.sh --debug dev --uglify fast --verbose
. Beispiel: gist.github.com/hfossli/4368aa5a577742c3c9f9266ed214aa58./script.sh -d dev -d prod
würde dazu führendeploy == 'prod'
. Ich habe es trotzdem benutzt: P :): +1:./script.sh -d
keinen Fehler erzeugen würde, sondern nur$deploy
eine leere Zeichenfolge setzen würde.von: digitalpeer.com mit geringfügigen Änderungen
Verwendungszweck
myscript.sh -p=my_prefix -s=dirname -l=libname
Zum besseren Verständnis
${i#*=}
suchen Sie in diesem Handbuch nach "Entfernen von Teilzeichenfolgen" . Es ist funktional äquivalent zu`sed 's/[^=]*=//' <<< "$i"`
dem , was einen unnötigen Unterprozess`echo "$i" | sed 's/[^=]*=//'`
aufruft oder der zwei unnötige Unterprozesse aufruft .quelle
mount -t tempfs ...
. Man kann dies wahrscheinlich über so etwas wiewhile [ $# -ge 1 ]; do param=$1; shift; case $param in; -p) prefix=$1; shift;;
etc beheben-vfd
kombinierten Stiloptionen umgehen .getopt()
Ichgetopts()
bin eine gute Option. Von hier gestohlen :quelle
$*
ist gebrochene Verwendung vongetopt
. (Argumente werden mit Leerzeichen versehen.) Siehe meine Antwort für die ordnungsgemäße Verwendung.Auf die Gefahr hin, ein weiteres zu ignorierendes Beispiel hinzuzufügen, ist hier mein Schema.
-n arg
und--name=arg
Hoffe, es ist nützlich für jemanden.
quelle
*) die "unrecognized argument: $1"
oder die Argumente in einer Variablen zusammenfassen*) args+="$1"; shift 1;;
.shift 2
, dieshift
zweimal statt ausgegeben wirdshift 2
. Schlug die Bearbeitung vor.Ich bin ungefähr 4 Jahre zu spät bei dieser Frage, möchte aber etwas zurückgeben. Ich habe die früheren Antworten als Ausgangspunkt verwendet, um meine alte Ad-hoc-Parameteranalyse aufzuräumen. Ich habe dann den folgenden Vorlagencode überarbeitet. Es verarbeitet sowohl lange als auch kurze Parameter mit = oder durch Leerzeichen getrennten Argumenten sowie mehrere kurze Parameter, die zusammen gruppiert sind. Schließlich werden alle nicht parametrischen Argumente wieder in die Variablen $ 1, $ 2 .. eingefügt. Ich hoffe es ist nützlich.
quelle
-c1
. Und die Verwendung von=
, um kurze Optionen von ihren Argumenten zu trennen, ist ungewöhnlich ...Ich fand die Angelegenheit, tragbares Parsing in Skripten zu schreiben, so frustrierend, dass ich Argbash geschrieben habe - einen FOSS-Codegenerator, der den Argument-Parsing-Code für Ihr Skript generieren kann und einige nette Funktionen hat:
https://argbash.io
quelle
Meine Antwort basiert größtenteils auf der Antwort von Bruno Bronosky , aber ich habe seine beiden reinen Bash-Implementierungen zu einer zusammengefasst, die ich ziemlich häufig verwende.
Auf diese Weise können Sie sowohl durch Leerzeichen getrennte Optionen / Werte als auch gleich definierte Werte festlegen.
So können Sie Ihr Skript ausführen mit:
ebenso gut wie:
und beide sollten das gleiche Endergebnis haben.
PROS:
Ermöglicht sowohl -arg = Wert als auch -arg Wert
Funktioniert mit jedem Arg-Namen, den Sie in Bash verwenden können
Pure Bash. Keine Notwendigkeit, getopt oder getopts zu lernen / zu verwenden
Nachteile:
Args können nicht kombiniert werden
Dies sind die einzigen Vor- und Nachteile, die mir auf den ersten Blick einfallen
quelle
Ich denke, dieser ist einfach genug zu benutzen:
Aufrufbeispiel:
quelle
-a=1
als Argc-Stil zu verwenden. Ich bevorzuge es, zuerst die Hauptoptionsoptionen und später die speziellen Optionen mit einfachem Abstand zu setzen-o option
. Ich bin auf der Suche nach dem einfachsten gegen besseren Weg, um Argumente zu lesen../myscript -v -d fail -o /fizz/someOtherFile -f ./foo/bar/someFile
mit Ihrem eigenen Skript überprüfen . -d Option ist nicht als d:Um die hervorragende Antwort von @guneysus zu erweitern, finden Sie hier eine Optimierung, mit der der Benutzer die von ihm bevorzugte Syntax verwenden kann, z
vs.
Das heißt, die Gleichheit kann durch Leerzeichen ersetzt werden.
Diese "Fuzzy-Interpretation" gefällt Ihnen vielleicht nicht, aber wenn Sie Skripte erstellen, die mit anderen Dienstprogrammen austauschbar sind (wie dies bei meinen der Fall ist, die mit ffmpeg funktionieren müssen), ist die Flexibilität hilfreich.
quelle
Dieses Beispiel zeigt, wie kurze und lange Parameter mit und ohne einen folgenden erforderlichen Wert verwendet
getopt
undeval
undHEREDOC
undshift
behandelt werden. Auch die switch / case-Anweisung ist kurz und leicht zu befolgen.Die wichtigsten Zeilen des obigen Skripts sind folgende:
Kurz, auf den Punkt, lesbar und handhabt fast alles (IMHO).
Hoffe das hilft jemandem.
quelle
Ich gebe Ihnen die Funktion
parse_params
, die Parameter über die Befehlszeile analysiert.--all
gleich-all
gleichall=all
)Das folgende Skript ist eine Demonstration zum Kopieren und Einfügen.
show_use
Informationen zur Verwendung finden Sie unter Funktionparse_params
.Einschränkungen:
-d 1
)--any-param
und-anyparam
sind gleichwertigeval $(parse_params "$@")
muss innerhalb der Bash- Funktion verwendet werden ( funktioniert nicht im globalen Bereich)quelle
show_use "$@"
EasyOptions erfordert keine Analyse:
quelle
getopts funktioniert hervorragend, wenn Sie # 1 installiert haben und # 2 beabsichtigen, es auf derselben Plattform auszuführen. OSX und Linux (zum Beispiel) verhalten sich in dieser Hinsicht unterschiedlich.
Hier ist eine (nicht getopts) Lösung, die gleich-, ungleich- und boolesche Flags unterstützt. Zum Beispiel könnten Sie Ihr Skript folgendermaßen ausführen:
quelle
So mache ich es in einer Funktion, um zu vermeiden, dass getopts gleichzeitig irgendwo höher im Stapel ausgeführt werden:
quelle
Als Erweiterung der Antwort von @ bruno-bronosky habe ich einen "Präprozessor" hinzugefügt, um einige gängige Formatierungen zu handhaben:
--longopt=val
in--longopt val
-xyz
in-x -y -z
--
die Angabe des Endes von Flagsquelle
Es gibt verschiedene Möglichkeiten, cmdline-Argumente zu analysieren (z. B. GNU getopt (nicht portabel) gegen BSD (OSX) getopt gegen getopts) - alles problematisch. Diese Lösung ist
=
Trennzeichen verwenden-vxf
Beispiele: Beliebig von
quelle
Ich möchte meine Version der Optionsanalyse anbieten, die Folgendes ermöglicht:
Berücksichtigt dies auch (könnte unerwünscht sein):
Sie müssen vor der Verwendung entscheiden, ob = für eine Option verwendet werden soll oder nicht. Dies dient dazu, den Code sauber zu halten (ish).
quelle
Lösung, die unbehandelte Argumente bewahrt. Demos enthalten.
Hier ist meine Lösung. Es ist SEHR flexibel und sollte im Gegensatz zu anderen keine externen Pakete erfordern und übrig gebliebene Argumente sauber behandeln.
Verwendung ist:
./myscript -flag flagvariable -otherflag flagvar2
Sie müssen lediglich die Zeile mit den gültigen Flags bearbeiten. Es wird ein Bindestrich vorangestellt und alle Argumente durchsucht. Es definiert dann das nächste Argument als Flaggenname, z
Der Hauptcode (Kurzversion, ausführlich mit Beispielen weiter unten, auch eine Version mit Fehler):
Die ausführliche Version mit integrierten Echo-Demos:
Letzteres ist ein Fehler, wenn ein ungültiges Argument durchlaufen wird.
Vorteile: Was es macht, geht es sehr gut. Es werden nicht verwendete Argumente beibehalten, die viele der anderen Lösungen hier nicht haben. Außerdem können Variablen aufgerufen werden, ohne im Skript von Hand definiert zu werden. Es ermöglicht auch die Vorbelegung von Variablen, wenn kein entsprechendes Argument angegeben wird. (Siehe ausführliches Beispiel).
Nachteile: Eine einzelne komplexe Argumentzeichenfolge kann nicht analysiert werden, z. B. würde -xcvf als einzelnes Argument verarbeitet. Sie könnten etwas leicht zusätzlichen Code in meinen schreiben, der diese Funktionalität hinzufügt.
quelle
Ich möchte mein Projekt einreichen: https://github.com/flyingangel/argparser
So einfach ist das. Die Umgebung wird mit Variablen gefüllt, die denselben Namen wie die Argumente haben
quelle
Beachten Sie, dass
getopt(1)
ein kurzer Fehler von AT & T war.getopt wurde 1984 erstellt, aber bereits 1986 begraben, weil es nicht wirklich verwendbar war.
Ein Beweis für die Tatsache , dass
getopt
sehr veraltet ist , ist , dass dergetopt(1)
Mann Seite noch erwähnt"$*"
statt"$@"
, die mit dem auf den Bourne - Shell im Jahr 1986 zusammen hinzugefügt wurdegetopts(1)
Shell builtin , um mit Argumenten mit Leerzeichen innerhalb zu befassen.Übrigens: Wenn Sie lange Optionen in Shell-Skripten analysieren möchten, ist es möglicherweise von Interesse zu wissen, dass die
getopt(3)
Implementierung von libc (Solaris) undksh93
beide eine einheitliche Implementierung langer Optionen hinzugefügt haben, die lange Optionen als Aliase für kurze Optionen unterstützt. Dies bewirktksh93
und dieBourne Shell
Implementierung einer einheitlichen Schnittstelle für lange Optionen übergetopts
.Ein Beispiel für lange Optionen aus der Bourne Shell-Manpage:
getopts "f:(file)(input-file)o:(output-file)" OPTX "$@"
zeigt, wie lange Optionsaliasnamen sowohl in Bourne Shell als auch in ksh93 verwendet werden können.
Siehe die Manpage einer aktuellen Bourne Shell:
http://schillix.sourceforge.net/man/man1/bosh.1.html
und die Manpage für getopt (3) von OpenSolaris:
http://schillix.sourceforge.net/man/man3c/getopt.3c.html
und zuletzt die Manpage getopt (1), um das veraltete $ * zu überprüfen:
http://schillix.sourceforge.net/man/man1/getopt.1.html
quelle
Ich habe einen Bash-Helfer geschrieben, um ein schönes Bash-Tool zu schreiben
Projekthaus: https://gitlab.mbedsys.org/mbedsys/bashopts
Beispiel:
wird helfen:
genießen :)
quelle
Hier ist mein Ansatz - mit Regexp.
-qwerty
-q -w -e
--qwerty
=
Attribute angeben, aber die Attribute stimmen überein, bis Bindestrich + Leerzeichen "Trennzeichen" angezeigt werden. In--q=qwe ty
qwe ty
ist also ein Attribut-o a -op attr ibute --option=att ribu te --op-tion attribute --option att-ribute
ist also gültigSkript:
quelle
Angenommen , wir ein Shell - Skript namens erstellen
test_args.sh
wie folgtNachdem wir den folgenden Befehl ausgeführt haben:
Die Ausgabe wäre:
quelle
Verwenden Sie Modul "Argumente" aus Bash-Modulen
Beispiel:
quelle
Positions- und Flaggenargumente mischen
--param = arg (gleich begrenzt)
Frei mischende Flags zwischen Positionsargumenten:
kann mit einem ziemlich präzisen Ansatz erreicht werden:
--param arg (durch Leerzeichen getrennt)
Es ist normalerweise klarer, nicht zu mischen
--flag=value
und zu stylen--flag value
.Dies ist ein wenig schwierig zu lesen, aber es ist immer noch gültig
Quelle
quelle
Hier ist ein Getopts, der das Parsen mit minimalem Code erreicht und es Ihnen ermöglicht, zu definieren, was Sie in einem Fall mit eval mit Teilzeichenfolge extrahieren möchten.
Grundsätzlich
eval "local key='val'"
Deklariert die Variablen als Einheimische anstelle von Globalen als die meisten Antworten hier.
Genannt als:
Das $ {k: 3} ist im Grunde ein Teilstring, um den ersten
---
aus dem Schlüssel zu entfernen .quelle
Dies kann auch hilfreich sein, um zu wissen, dass Sie einen Wert festlegen können. Wenn jemand Eingaben bereitstellt, überschreiben Sie den Standardwert mit diesem Wert.
myscript.sh -f ./serverlist.txt oder einfach ./myscript.sh (und es werden Standardeinstellungen verwendet)
quelle
Eine andere Lösung ohne getopt [s], POSIX, alter Unix-Stil
Ähnlich wie bei der Lösung, die Bruno Bronosky hier gepostet hat, handelt es sich um eine Lösung ohne Verwendung von
getopt(s)
.Das Hauptunterscheidungsmerkmal meiner Lösung besteht darin, dass Optionen miteinander verkettet werden können, genau wie dies
tar -xzf foo.tar.gz
gleich isttar -x -z -f foo.tar.gz
. Und genau wie intar
,ps
usw. der führenden Bindestrich ist optional für einen Block von Short - Optionen (aber dies kann leicht geändert werden). Es werden auch lange Optionen unterstützt (aber wenn ein Block mit einem beginnt, sind zwei führende Bindestriche erforderlich).Code mit Beispieloptionen
Die Beispielverwendung finden Sie in den Beispielen weiter unten.
Position von Optionen mit Argumenten
Für was es dort wert ist, sind die Optionen mit Argumenten nicht die letzten (nur lange Optionen müssen sein). Während z. B. in
tar
(zumindest in einigen Implementierungen) dief
Optionen zuletzt sein müssen, da der Dateiname folgt (tar xzf bar.tar.gz
funktioniert,tar xfz bar.tar.gz
aber nicht funktioniert), ist dies hier nicht der Fall (siehe die späteren Beispiele).Mehrere Optionen mit Argumenten
Als weiteren Bonus werden die Optionsparameter in der Reihenfolge der Optionen von den Parametern mit den erforderlichen Optionen verbraucht. Schauen Sie sich hier die Ausgabe meines Skripts mit der Befehlszeile
abc X Y Z
(oder-abc X Y Z
) an:Auch lange Optionen verkettet
Sie können auch lange Optionen im Optionsblock haben, da diese zuletzt im Block vorkommen. Die folgenden Befehlszeilen sind also alle gleichwertig (einschließlich der Reihenfolge, in der die Optionen und ihre Argumente verarbeitet werden):
-cba Z Y X
cba Z Y X
-cb-aaa-0-args Z Y X
-c-bbb-1-args Z Y X -a
--ccc-2-args Z Y -ba X
c Z Y b X a
-c Z Y -b X -a
--ccc-2-args Z Y --bbb-1-args X --aaa-0-args
All dies führt zu:
Nicht in dieser Lösung
Optionale Argumente
Optionen mit optionalen Argumenten sollten mit ein wenig Arbeit möglich sein, z. B. indem Sie nach vorne schauen, ob es einen Block ohne Bindestrich gibt. Der Benutzer müsste dann vor jedem Block nach einem Block mit einem Parameter mit einem optionalen Parameter einen Bindestrich setzen. Möglicherweise ist dies zu kompliziert, um mit dem Benutzer zu kommunizieren, sodass in diesem Fall besser nur ein führender Bindestrich erforderlich ist.
Mit mehreren möglichen Parametern wird es noch komplizierter. Ich würde davon abraten, die Optionen so zu gestalten, dass sie klug sind, indem ich feststelle, ob ein Argument dafür geeignet ist oder nicht (z. B. wenn eine Option nur eine Zahl als optionales Argument verwendet), da dies in Zukunft möglicherweise nicht mehr funktioniert.
Ich persönlich bevorzuge zusätzliche Optionen anstelle optionaler Argumente.
Optionsargumente mit Gleichheitszeichen
Genau wie bei optionalen Argumenten bin ich kein Fan davon (Übrigens, gibt es einen Thread, in dem die Vor- und Nachteile verschiedener Parameterstile diskutiert werden?), Aber wenn Sie dies möchten, können Sie es wahrscheinlich selbst implementieren, wie unter http: // mywiki.wooledge.org/BashFAQ/035#Manual_loop mit einer
--long-with-arg=?*
case-Anweisung und anschließendem Entfernen des Gleichheitszeichens (dies ist übrigens die Site, die besagt, dass die Verkettung von Parametern mit einigem Aufwand möglich ist, aber [es] als Übung für den Leser hinterlassen hat "was mich dazu brachte, sie beim Wort zu nehmen, aber ich fing von vorne an).Weitere Hinweise
POSIX-konform, funktioniert auch auf alten Busybox - Setups ich zu tun hatte (mit zB
cut
,head
undgetopts
fehlt).quelle