Ich bin verwirrt, wie optionale Argumente / Flags beim Schreiben eines Bash-Skripts für das folgende Programm eingefügt werden sollen:
Das Programm erfordert zwei Argumente:
run_program --flag1 <value> --flag2 <value>
Es gibt jedoch mehrere optionale Flags:
run_program --flag1 <value> --flag2 <value> --optflag1 <value> --optflag2 <value> --optflag3 <value> --optflag4 <value> --optflag5 <value>
Ich möchte das Bash-Skript so ausführen, dass es Benutzerargumente akzeptiert. Wenn Benutzer nur zwei Argumente der Reihe nach eingeben, wäre dies:
#!/bin/sh
run_program --flag1 $1 --flag2 $2
Was aber, wenn eines der optionalen Argumente enthalten ist? Ich würde denken, dass es sein würde
if [ --optflag1 "$3" ]; then
run_program --flag1 $1 --flag2 $2 --optflag1 $3
fi
Aber was ist, wenn 4 $ gegeben werden, aber nicht 3 $?
shell-script
arguments
ShanZhengYang
quelle
quelle
getopts
ist was du willst. Ohne dies könnten Sie eine Schleife mit einer switch-Anweisung verwenden, um jedes optionale oder nicht optionale Flag zu erkennen.getopts
müsste ich jede Argumentkombination angeben? 3 & 4, 3 & 5, 3 & 4 & 5 usw.?getopts
. Angenommen, ich zwinge Benutzer, das Skript mit allen Argumenten auszuführen:run_program.sh VAL VAL FALSE FALSE FALSE FALSE FALSE
das Programm wird ausgeführt alsprogram --flag1 VAL --flag2 VAL
. Wenn Sie ausgeführt werdenrun_program.sh VAL VAL FALSE 10 FALSE FALSE FALSE
, wird das Programm als ausgeführtprogram --flag1 VAL --flag2 VAL --optflag2 10
. Wie können Sie ein solches Verhalten erreichengetopts
?Antworten:
Dieser Artikel zeigt zwei verschiedene Möglichkeiten -
shift
undgetopts
(und erläutert die Vor- und Nachteile der beiden Ansätze).Wenn
shift
Ihr Skript betrachtet wird$1
, entscheidet es, welche Aktion ausgeführt werden soll, und führtshift
sie dann aus , wechselt$2
zu$1
,$3
zu$2
usw.Beispielsweise:
Mit
getopts
definieren Sie die (kurzen) Optionen imwhile
Ausdruck:Offensichtlich sind dies nur Code-Schnipsel, und ich habe die Validierung ausgelassen - um zu überprüfen, ob die obligatorischen Argumente flag1 und flag2 gesetzt sind usw.
Welchen Ansatz Sie verwenden, ist bis zu einem gewissen Grad Geschmackssache - wie portabel Ihr Skript sein soll, ob Sie nur mit kurzen (POSIX) Optionen leben können oder ob Sie lange (GNU) Optionen wünschen usw.
quelle
while (( $# ))
stattwhile :;
und oft mit einem Fehler in dem*
Fall zu beendenset -o nounset
der ersten Lösung tritt ein Fehler auf, wenn kein Parameter angegeben wird. Fix:case ${1:-} in
Verwenden Sie ein Array.
Dadurch werden Argumente mit Leerzeichen korrekt behandelt.
[Bearbeiten] Ich habe die ungefähr äquivalente Syntax verwendet,
args=( "${args[@]}" --optflag1 "$3" )
aber G-Man schlug einen besseren Weg vor.quelle
args+=( --optflag1 "$3" )
. Vielleicht möchten Sie meine Antwort auf unser Nachschlagewerk, Auswirkungen auf die Sicherheit , wenn eine Variable nicht in Bash / POSIX-Shells zitiert wird, sehen, in denen ich diese Technik diskutiere (das Erstellen einer Befehlszeile in einem Array durch bedingtes Anhängen optionaler Argumente).[@]
ein ausreichendes Werkzeug hatte, um mein Problem zu lösen.In einem Shell-Skript lauten die Argumente "$ 1", "$ 2", "$ 3" usw. Die Anzahl der Argumente beträgt $ #.
Wenn Ihr Skript keine Optionen erkennt, können Sie die Optionserkennung weglassen und alle Argumente als Operanden behandeln.
Verwenden Sie die integrierten getopts, um Optionen zu erkennen
quelle
Wenn Ihre Eingabeoptionen positionell sind (Sie wissen, an welchen Stellen sie sich befinden) und nicht mit Flags angegeben sind, möchten Sie lediglich die Befehlszeile erstellen. Bereiten Sie einfach die Befehlsargumente für alle vor:
Wenn die Parameter nicht angegeben werden, sind die entsprechenden Zeichenfolgen leer und werden zu nichts erweitert. Beachten Sie, dass in der letzten Zeile keine Anführungszeichen stehen. Das liegt daran, dass die Shell die Parameter in Wörter aufteilen soll (geben
--flag1
und$1
als separate Argumente für Ihr Programm). Dies geht natürlich schief, wenn Ihre ursprünglichen Parameter Leerzeichen enthalten. Wenn Sie derjenige sind, der dies ausführt, können Sie es verlassen. Wenn es sich jedoch um ein allgemeines Skript handelt, kann es zu unerwartetem Verhalten kommen, wenn der Benutzer etwas mit Leerzeichen eingibt. Um damit umzugehen, müssen Sie den Code etwas hässlicher machen.Das
x
Präfix im[]
Test ist für den Fall vorhanden$3
oder$4
leer. In diesem Fall würde bash erweitern[ FALSE != $3 ]
in[ FALSE != ]
dem ein Syntaxfehler, so ein weiteres beliebige Zeichen gibt es gegen diese zu schützen. Dies ist eine sehr häufige Methode, die Sie in vielen Skripten sehen werden.Ich habe
OPTFLAG1
und der Rest von ihnen zu""
Beginn eingestellt, nur um sicherzugehen (falls sie zuvor auf etwas eingestellt waren), aber wenn sie nicht tatsächlich in der Umgebung deklariert wurden, müssen Sie dies nicht unbedingt tun.Ein paar zusätzliche Bemerkungen:
runprogram
mit Flags. Darum gehtJohn N
es. Dortgetopts
wird es nützlich.-
) verwenden, um einen leeren Wert zu signalisieren, oder einfach eine leere Zeichenfolge übergeben""
, wenn dies ansonsten kein gültiger Wert des Parameters ist. Leere Zeichenfolge macht den Test auch kürzer, verwenden Sie einfachif [ -n "$3" ]
.""
leere Parameter verwenden, wie oben vorgeschlagen, können Sie trotzdem alle nachgestellten Leergut überspringen.Diese Methode ist so ziemlich die Art und Weise, wie Optionen an Compiler in Makefiles übergeben werden.
Und wieder - wenn Eingaben Leerzeichen enthalten können, wird es hässlich.
quelle