Ist es beim Ausführen eines Shell-Skripts möglich, bestimmte Positionsparameter zu übergeben, ohne sie alle der Reihe nach eingeben zu müssen?

13

Zum Beispiel, wenn ich ein Skript ./foo habe, das 10 Parameter akzeptiert, und ich nur den 8. Parameter übergeben möchte. Die einzige Möglichkeit, wie ich das derzeit weiß, ist:

./foo '' '' '' '' '' '' '' 'bar'

Gibt es einen einfacheren / besseren Weg?

Kerry Randolph
quelle
1
Aus diesem Grund verwenden Programme normalerweise Optionen anstelle von Positionsparametern, wenn Sie viele Parameter haben.
Barmar

Antworten:

4

Eine andere Möglichkeit, dies zu tun, besteht darin, den zu deklarierenden Parameter zu benennen und dies dann zu tun:

{   cat >./foo 
    chmod +x ./foo
    eight=declared ./foo
    eight=declared_and_preferred \
        ./foo 1 2 3 4 5 6 7 8
    ./foo 1 2 3 4 5 6 7 8
    ./foo
} <<\SCRIPT
#!/usr/bin/sh
: ${eight:=${8:-some_default}}
printf '$eight = %s\n' "$eight"
#END
SCRIPT

AUSGABE

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default

Im obigen Beispiel wird die explizit deklarierte Umgebungsvariable dem Befehlszeilenargument vorgezogen, das Befehlszeilenargument wird jedoch verwendet, wenn die Umgebungsvariable entweder leer oder nicht gesetzt ist. Wenn sowohl die 8. Positions- als auch die Umgebungsvariable $eightleer oder nicht gesetzt sind, wird der Standardwert some_default zugewiesen $eight. In beiden Fällen :kann das aus den Anweisungen :-oder entfernt werden :=, wenn leer ein akzeptabler Wert sein sollte.

Die Variable $eighthätte auch so eingestellt werden können:

printf '$eight = %s\n' "${eight:=${8:-some_default}}"

... und die vorherige Zeile wurde komplett weggelassen, aber ich wollte demonstrieren, dass das Deklarieren einer Variablen auf diese Weise zu einem dauerhaften Wert führt, und habe dies in zwei Befehlen getan. In beiden Fällen $eightwird der endgültige Wert dieser zusammengesetzten Parametererweiterung festgelegt.

getopts- für robuste Skripte - ist oft die beste Möglichkeit, mit Befehlsoptionen umzugehen . Andererseits sind Positionsparameter fast immer das einfachste Mittel, um Operanden in einem Skript robust zu behandeln .

Beispielsweise:

touch file$(seq -ws\ file 100)
./foo *

AUSGABE

$eight = file008

Dort sehen wir nur den achten Operanden, aber 101 davon sind aus meinem Testverzeichnis entfernt.

mikeserv
quelle
18

Angenommen, Sie können das Skript ändern, sollten Sie die Verwendung optionaler Parameter (Optionen) anstelle der erforderlichen Parameter (Argumente) in Betracht ziehen.

Wenn Sie jeden der ersten 7 sieben Parameter als Option haben und standardmäßig die leere Zeichenfolge verwenden, können Sie Folgendes tun:

./foo bar

Wenn Sie eine POSIX-kompatible Shell verwenden , können Sie das getoptsDienstprogramm oder das Programm verwenden getopt. bash- wie die meisten Muscheln - getoptsals eingebautes Angebot . In beiden Fällen ist es einfacher, einen eigenen Befehlszeilenparser zu erstellen.

Sofern Sie nicht so etwas wie die letzten X-Nicht-Optionsargumente als Werte für die letzten Y-Argumente und XY-Optionsargumente implementieren, müssen Sie Optionszeichenfolgen vor jeder der 7 (jetzt leeren) Zeichenfolgen angeben, wenn Sie eine dieser Zeichenfolgen festlegen möchten. Dies ist jedoch keine übliche Praxis, normalerweise ist eine Option immer eine Option und ein Argument ein Argument, und die Reihenfolge der Option "Einfügen" ist frei.

Anthon
quelle
5
+1für getopt(s). Positionsparameter sind eine traurige Zeit und sollten vermieden werden.
HalosGhost