Ich habe ein Bash-Skript, das eine Befehlszeile in einer Zeichenfolge basierend auf einigen Parametern erstellt, bevor es auf einmal ausgeführt wird. Die Teile, die mit der Befehlszeichenfolge verknüpft sind, sollen durch Pipes getrennt werden, um ein "Streaming" von Daten durch jede Komponente zu ermöglichen.
Ein sehr vereinfachtes Beispiel:
#!/bin/bash
part1=gzip -c
part2=some_other_command
cmd="cat infile"
if [ ! "$part1" = "" ]
then
cmd+=" | $part1"
fi
if [ ! "$part2" = "" ]
then
cmd+=" | $part2"
fi
cmd+="> outfile"
#show command. It looks ok
echo $cmd
#run the command. fails with pipes
$cmd
Aus irgendeinem Grund scheinen die Pfeifen nicht zu funktionieren. Wenn ich dieses Skript ausführe, erhalte ich verschiedene Fehlermeldungen, die sich normalerweise auf den ersten Teil des Befehls beziehen (vor der ersten Pipe).
Meine Frage ist also, ob es möglich ist, einen Befehl auf diese Weise zu erstellen, und wie lässt sich dies am besten erreichen?
infile
es im aktuellen Verzeichnis existiert?Antworten:
Es hängt alles davon ab, wann die Dinge bewertet werden. Bei der Eingabe
$cmd
wird der gesamte Rest der Zeile als Argument an das erste Wort in übergeben$cmd
.Dies zeigt, dass die an den
echo
Befehl übergebenen Argumente "/etc/passwd
", "|
" (das vertikale Strichzeichen), "wc
" und "-l
" sind.Von
man bash
:quelle
Eine Lösung für dieses Problem besteht in der Verwendung von "eval". Dies stellt sicher, dass die Art und Weise, in der der String von der Bash interpretiert wird, vergessen wird und das Ganze so gelesen wird, als ob es direkt in eine Shell geschrieben worden wäre (was genau das ist, was wir wollen).
Also im obigen Beispiel ersetzen
mit
Ich habe es gelöst.
quelle
eval foo "a b"
wäre das gleiche wieeval foo "a" "b"
.@waltinator hat bereits erklärt, warum dies nicht wie erwartet funktioniert. Eine andere Möglichkeit besteht
bash -c
darin, Ihren Befehl auszuführen:quelle
bash -c
, sonderneval
den Befehl im aktuellen Prozess auszuführen.Möglicherweise ist es besser,
eval
ein Bash-Array und dessen Inline-Erweiterung zu vermeiden und nur zu verwenden, um alle Argumente aufzubauen und sie dann gegen den Befehl auszuführen.quelle