2015-05-06 7 views
5

Ich schreibe ein Bash-Skript, das einige optionale Parameter aufnimmt. Ich möchte sie übersetzen und an ein anderes Skript übergeben. Allerdings habe ich Schwierigkeiten, die optionalen Parameter elegant zu übergeben.Wie kann ich optionale Parameter an einen anderen Befehl in einem Bash-Skript übergeben?

Hier ist eine Übersicht darüber, was konnte ich in Pseudo-Code zum Laufen zu bringen:

a.sh:

if arg1 in arguments; then 
    firstArg="first argument" 
fi 
if arg2 in arguments; then 
    secondArg="second argument" 
fi 

./b.sh $firstArg $secondArg "default argument" 

Beachten Sie die Räume in den Argumenten.

b.sh:

for arg in "[email protected]" 
do 
    echo $arg 
done 

Ich möchte b.sh nennen, optional mit firstArg und secondArg und ein Standardargument wie so:

./b.sh $firstArg $secondArg "default argument" 

Das Problem dabei ist, dass, wenn $firstArg oder $secondArg Sind Zeichenfolgen mit Leerzeichen, werden sie als mehrere Argumente dargestellt, und die Ausgabe wird etwa lauten:

Okay, das ist einfach zu beheben, lassen Sie uns die gesamte Kette der Argumente erfassen, indem Sie Anführungszeichen um es wie so hinzufügen:

./b.sh "$firstArg" "$secondArg" "defaultArg" 

Problem ist, wenn beispielsweise firstArg nicht gesetzt ist, führt dies zu eine leere Zeile (wie es "" als Parameter interpretiert wird), so dass der Ausgang so etwas wie sein:

(blank line here) 
second argument 
defaultArg 

habe ich auch versucht, einen String konstruieren und an den Shell-Skript vorbei, aber es funktioniert nicht scheinen so zu funktionieren (es int Erregt die ganze Zeichenfolge als Argument, auch wenn ich die Argumente durch Anführungszeichen getrennt hinzufüge).

Beachten Sie, dass das Aufrufen von b.sh von meiner Befehlszeile mit den angegebenen Argumenten funktioniert. Gibt es eine Möglichkeit zu simulieren, wie das in einem Bash-Skript funktioniert?

+1

Abgesehen: Nur weil ich Ihren Vorsprung bin kopieren und mit '.sh' Erweiterungen auf ausführbaren Dateien (d. h. Dateien mit der + x-Berechtigung, gegen die ein 'execv()' - Familienaufruf erfolgreich ist) bedeutet nicht, dass es eine gute Idee ist. Im Allgemeinen sollten Befehle in UNIX keine Erweiterungen haben, egal ob sie über ein Shell-Skript, ein Python-Skript, eine kompilierte Binärdatei usw. bereitgestellt werden. –

+0

Können Sie explizit klären, ob dies für Code ist, der '#! bin/sh' oder '#!/bin/bash'? –

+0

Ich benutze bash. – Andrew

Antwort

7

Wenn Sie buchstäblich wollen gegeben, alle Argumente kopieren, sondern fügen Sie ein mehr:

# this works in any POSIX shell 
./b.sh "[email protected]" defaultArg 

Alternativ explizit firstArg und secondArg, passieren, aber nur, wenn sie vorhanden sind (beachten Sie, dass Set-to-ein-Leer -Wertes zählt als "bestehende" hier):

# this works in any POSIX shell 
./b.sh ${firstArg+"$firstArg"} ${secondArg+"$secondArg"} defaultArg 

Wenn Sie behandeln möchten set-to-ein-leer-Wert als nicht vorhanden:

# this works in any POSIX shell 
./b.sh ${firstArg:+"$firstArg"} ${secondArg:+"$secondArg"} defaultArg 

Ein alternativer Ansatz ist es, eine Reihe von Argumenten aufzubauen:

# this requires bash or another shell with arrays and append syntax 
# be sure any script using this starts with #!/bin/bash 
b_args=() 
[[ $firstArg ]] && b_args+=("$firstArg") 
[[ $secondArg ]] && b_args+=("$secondArg") 
b_args+=("default argument") 
./b.sh "${b_args[@]}" 

Wenn Sie etwas mit der gleichen Flexibilität wie die Array-Verfahren wollen, aber ohne die Kompatibilitätsprobleme, definieren eine Funktion; in ihm, können Sie sicher "[email protected]" außer Kraft setzen, ohne den Rest des Skripts zu beeinflussen:

runB() { 
    set -- 
    [ -n "$firstArg" ] && set -- "[email protected]" "$firstArg" 
    [ -n "$secondArg" ] && set -- "[email protected]" "$secondArg" 
    ./b.sh "[email protected]" "default argument" 
} 
+0

Ist hier nicht "$ @" falsch? Es wird nicht mehr Gegenstand der Worttrennung sein, oder? – hek2mgl

+0

@ hek2mgl, was? Nein, Worttrennung ist hier eindeutig nicht erwünscht. –

+0

Gute Antwort! Ich habe die Frage beim Posten des Kommentars nicht richtig beantwortet. – hek2mgl

1

ein Array verwenden:

args=() 

if [ ... ]; then 
    args+=("first argument") 
fi 

if [ ... ]; then 
    args+=("second argument") 
fi 

./b.sh "${args[@]}" "default argument" 
+0

@EtanReisner Nein, nicht, weil im Beispiel von OP '$ firstArg' überhaupt nicht gesetzt (aber verwendet) wird, aber wenn es gesetzt wird, wird es auf ein String-Literal gesetzt (dasselbe im obigen Snippet). –

+0

Ah, ich nahm an, das waren Platzhalter für die eigentlichen ersten und zweiten Argumente und nicht wörtliche Strings (im OP und auch hier) und da Sie die eigentlichen Tests an den Argumenten selbst weggelassen haben, habe ich diese nicht ausgefüllt. Wie geschrieben hat dieses Problem nicht, aber wie geschrieben, ist dies auch nur die Hälfte einer Lösung (und ich denke, es löst es nicht richtig). –

+0

Woher kommst du? Das OP, das './b.sh" $ firstArg "" $ secondArg "" defaultArg "' als mögliche Lösung gibt (und seinen einzigen Fehler beschreibt, indem es leere Argumente durchläuft, anstatt sie überhaupt nicht zu liefern), zeigt die Verwendung an von literalen Strings '" erstes Argument "' und '" zweites Argument "' war nur Schlamperei früher in der Frage. –

Verwandte Themen