1230 Stimmen

Alle Argumente in einem Bash-Shell-Skript übergeben.

Ich schreibe ein sehr einfaches Skript, das ein anderes Skript aufruft, und ich muss die Parameter von meinem aktuellen Skript zum auszuführenden Skript übertragen.

Zum Beispiel heißt mein Skript foo.sh und ruft bar.sh auf.

foo.sh:

bar $1 $2 $3 $4

Wie kann ich das machen, ohne jeden Parameter explizit anzugeben?

0 Stimmen

0 Stimmen

Ich musste diese Lösung für meinen Anwendungsfall verwenden.

1930voto

Sdaz MacSkibbons Punkte 26240

Verwenden Sie "$@" anstelle von einfach $@, wenn Sie möchten, dass Ihre Parameter tatsächlich gleich übergeben werden.

Beobachten:

$ cat no_quotes.sh
#!/bin/bash
echo_args.sh $@

$ cat quotes.sh
#!/bin/bash
echo_args.sh "$@"

$ cat echo_args.sh
#!/bin/bash
echo Erhalten: $1
echo Erhalten: $2
echo Erhalten: $3
echo Erhalten: $4

$ ./no_quotes.sh first second
Erhalten: first
Erhalten: second
Erhalten:
Erhalten:

$ ./no_quotes.sh "one quoted arg"
Erhalten: one
Erhalten: quoted
Erhalten: arg
Erhalten:

$ ./quotes.sh first second
Erhalten: first
Erhalten: second
Erhalten:
Erhalten:

$ ./quotes.sh "one quoted arg"
Erhalten: one quoted arg
Erhalten:
Erhalten:
Erhalten:

13 Stimmen

Dies funktioniert nur für die reine Durchleitung von zitierten/escaped Zeichenfolgen: Beobachten: cat rsync_foo.sh #!/bin/bash echo "$@" rsync "$@" ./rsync_foo.sh -n "bar me" bar2 bar me bar2Skipped Verzeichnis bar me Ist es möglich, ein Shell-Skript zu haben, das die wahre ursprüngliche Befehlszeile sehen kann, vollständig mit Anführungszeichen oder escaped Zeichenfolgen?

3 Stimmen

Was ist mit dem Übergeben von Flaggen? zB, './bar.sh --with-stuff'

9 Stimmen

Ich schlage jedem vor, der das Thema Worttrennung besser verstehen möchte, hier mehr darüber zu lesen.

516voto

Chris Johnsen Punkte 199970

Für bash und andere Bourne-ähnliche Shells:

bar "$@"

13 Stimmen

@Amir: Nein, nicht für csh. Für das Wohl aller: keine Skripte in csh schreiben. Aber ich denke vielleicht wird $argv:q in einigen csh-Varianten funktionieren.

3 Stimmen

Vielen Dank! Wie gewünscht, werden dieselben Argumente weitergegeben, die vom Skript empfangen wurden - nicht ein großes Argument. Die Anführungszeichen sind notwendig. Funktioniert auch bei argumenten, die Leerzeichen enthalten, wenn sie in Anführungszeichen stehen.

29 Stimmen

Verwandt: Wenn Ihr Shell-Skript nur als Wrapper zum Ausführen von Java fungiert, erwägen Sie, die letzte Zeile exec java com.myserver.Program "$@" zu machen. Dies veranlasst Bash, in Java zu wechseln, anstatt darauf zu warten, dass es abgeschlossen ist. Sie verwenden also einen Prozessplatz weniger. Außerdem könnten einige ungewöhnliche Dinge passieren, wenn das übergeordnete Elternprozess (der Ihr Skript ausgeführt hat) es über die PID überwacht und erwartet, dass es der 'Java'-Prozess ist, wenn Sie kein exec ausführen; das exec veranlasst Java, dieselbe PID zu übernehmen.

121voto

miku Punkte 170688

Verwenden Sie "$@" (funktioniert für alle POSIX kompatiblen).

[...], bash bietet die "$@"-Variable, die sich auf alle durch Leerzeichen getrennten Befehlszeilenparameter ausdehnt.

Von Bash am Beispiel.

9 Stimmen

Also ist "$@" nicht nur Anführungszeichen um $@, sondern in der Tat eine andere integrierte Variable?

8 Stimmen

@ben Es handelt sich hierbei um eine einzelne Variable, aber um einen nützlichen Wert zu erhalten, der sich von dem (fehlerhaften) $* unterscheidet, müssen doppelte Anführungszeichen um sie gesetzt werden. Ich glaube, hier gibt es einen historischen Fortschritt; $* funktionierte nicht wie vorgesehen, daher wurde $@ erfunden, um es zu ersetzen; aber aufgrund der geltenden Quotenregeln sind die doppelten Anführungszeichen immer noch erforderlich (sonst fällt es auf die fehlerhafte Semantik von $* zurück).

9 Stimmen

"So ist "$@" nicht nur Anführungszeichen um $@, sondern tatsächlich eine andere integrierte Variable?" - Im Grunde genommen ja: stackoverflow.com/a/28099707/162094

117voto

JDS Punkte 1699

Ich merke, dass dies gut beantwortet wurde, aber hier ist ein Vergleich zwischen "$@" $@ "$*" und $*

Inhalt des Testskripts:

# cat ./test.sh
#!/usr/bin/env bash
echo "================================="

echo "In Anführungszeichen DOLLAR-AT"
for ARG in "$@"; do
    echo $ARG
done

echo "================================="

echo "NICHT in Anführungszeichen DOLLAR-AT"
for ARG in $@; do
    echo $ARG
done

echo "================================="

echo "In Anführungszeichen DOLLAR-STAR"
for ARG in "$*"; do
    echo $ARG
done

echo "================================="

echo "NICHT in Anführungszeichen DOLLAR-STAR"
for ARG in $*; do
    echo $ARG
done

echo "================================="

Jetzt führen Sie das Testskript mit verschiedenen Argumenten aus:

# ./test.sh  "arg mit Leerzeichen eins" "arg2" arg3
=================================
In Anführungszeichen DOLLAR-AT
arg mit Leerzeichen eins
arg2
arg3
=================================
NICHT in Anführungszeichen DOLLAR-AT
arg
mit
Leerzeichen
eins
arg2
arg3
=================================
In Anführungszeichen DOLLAR-STAR
arg mit Leerzeichen eins arg2 arg3
=================================
NICHT in Anführungszeichen DOLLAR-STAR
arg
mit
Leerzeichen
eins
arg2
arg3
=================================

102voto

Shital Shah Punkte 54846

Viele Antworten hier empfehlen $@ oder $* mit und ohne Anführungszeichen, jedoch scheint keine zu erklären, was diese wirklich tun und warum du es auf diese Weise machen solltest. Lass mich also diese ausgezeichnete Zusammenfassung von dieser Antwort "stehlen":

+--------+---------------------------+
| Syntax |   Effektives Ergebnis     |
+--------+---------------------------+
|   $*   |     $1 $2 $3 ... ${N}     |
+--------+---------------------------+
|   $@   |     $1 $2 $3 ... ${N}     |
+--------+---------------------------+
|  "$*"  |    "$1c$2c$3...c${N}"    |
+--------+---------------------------+
|  "$@"  | "$1" "$2" "$3" ... "${N}" |
+--------+---------------------------+

Beachte, dass Anführungszeichen den entscheidenden Unterschied ausmachen und ohne sie beide identisches Verhalten haben.

Für meinen Zweck musste ich Parameter von einem Skript auf ein anderes übergeben und dafür ist die beste Option:

# Datei: parent.sh
# wir haben einige Parameter, die an parent.sh übergeben werden
# die wir gerne an child.sh unverändert weitergeben möchten

./child.sh $*

Beachte, keine Anführungszeichen und $@ sollte auch in der obigen Situation funktionieren.

1 Stimmen

Du kannst das selbst überprüfen, indem du env --debug verwendest. Zum Beispiel, füge env --debug echo "$*" innerhalb einer Funktion hinzu und versuche sie mit verschiedenen Argumenten auszuführen.

3 Stimmen

Dein Beispiel ist falsch. $* übergibt sie nicht unverändert. Vielleicht hängt es davon ab, wie du "unverändert" definierst. Beispiel: Wenn du ./parent.sh 'a b' c aufrufst, dann würde im Elternskript $1 zu a b ausgewertet, aber im Kinderskript würde $1 nur zu a ausgewertet. Das ist also nicht das, was ich erwarte. Ich erwarte, dass beide Skripte dieselben Argumente "sehen" und das funktioniert nur mit ./child.sh "$@".

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X