Ich habe ein Skript geschrieben, das diese Argumente mit Anführungszeichen für mich generieren kann
Wenn die Ausgabe für die Shell korrekt in Anführungszeichen gesetzt ist und Sie der Ausgabe vertrauen , können Sie sie ausführen eval
.
Angenommen, Sie haben eine Shell, die Arrays unterstützt, ist es am besten, eine zu verwenden, um die erhaltenen Argumente zu speichern.
Wenn ./gen_args.sh
eine Ausgabe wie erzeugt wird 'foo bar' '*' asdf
, können wir eval "args=( $(./gen_args.sh) )"
ein Array args
mit den Ergebnissen auffüllen. Das wäre die drei Elemente foo bar
, *
, asdf
.
Wir können "${args[@]}"
wie gewohnt die Array-Elemente einzeln erweitern:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(Beachten Sie die Anführungszeichen. "${array[@]}"
Erweitert sich auf alle Elemente als eindeutige Argumente, die nicht geändert wurden. Ohne Anführungszeichen unterliegen die Array-Elemente einer Wortaufteilung . Siehe z. B. die Seite Arrays in BashGuide .)
Jedoch , eval
wird gerne weiter Shell Ersetzungen ausgeführt werden , so $HOME
in der Ausgabe zu Ihrem Home - Verzeichnis erweitern würde, und ein Befehl Substitution würde tatsächlich einen Befehl in der Shell - Lauf laufen eval
. Eine Ausgabe von "$(date >&2)"
würde ein einzelnes leeres Array-Element erstellen und das aktuelle Datum auf stdout drucken. Dies ist ein Problem, wenn gen_args.sh
die Daten von einer nicht vertrauenswürdigen Quelle wie einem anderen Host über das Netzwerk abgerufen werden und Dateinamen von anderen Benutzern erstellt werden. Die Ausgabe kann beliebige Befehle enthalten. (Wenn es get_args.sh
selbst böswillig wäre, müsste es nichts ausgeben, es könnte einfach die böswilligen Befehle direkt ausführen.)
Eine Alternative zu Shell-Zitaten, die ohne Auswertung nur schwer zu analysieren sind, besteht darin, in der Ausgabe Ihres Skripts ein anderes Zeichen als Trennzeichen zu verwenden. Sie müssten eine auswählen, die in den tatsächlichen Argumenten nicht benötigt wird.
Lassen Sie uns wählen #
und die Skriptausgabe haben foo bar#*#asdf
. Jetzt können wir die Erweiterung des Befehls ohne Anführungszeichen verwenden , um die Ausgabe des Befehls auf die Argumente aufzuteilen.
$ IFS='#' # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
Sie müssen IFS
später zurücksetzen, wenn Sie von der Wortaufteilung an anderer Stelle im Skript abhängig sind ( unset IFS
sollte funktionieren, um es zum Standard zu machen), und auch verwenden, set +f
wenn Sie später Globbing verwenden möchten.
Wenn Sie Bash oder eine andere Shell mit Arrays nicht verwenden, können Sie die Positionsparameter dafür verwenden. Ersetzen Sie args=( $(...) )
durch set -- $(./gen_args.sh)
und verwenden Sie "$@"
stattdessen "${args[@]}"
. (Auch hier benötigen Sie Anführungszeichen "$@"
, da sonst die Positionsparameter einer Wortaufteilung unterliegen.)
eval
verwendet werden, wird jedoch im Allgemeinen nicht empfohlen.xargs
ist auch etwas zu beachten