Verwenden Sie eval:
x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"
nicht Verwenden Sie eval
! Es besteht ein großes Risiko, dass willkürlicher Code ausgeführt wird.
BashFAQ-50 - Ich versuche, einen Befehl in eine Variable zu schreiben, aber die komplexen Fälle schlagen immer fehl.
Fügen Sie es in ein Array ein und erweitern Sie alle Wörter mit doppelten Anführungszeichen "${arr[@]}"
zu nicht Lassen Sie die IFS
teilen Sie die Wörter aufgrund von Word Splitting auf.
cmdArgs=()
cmdArgs=('date' '+%H:%M:%S')
und den Inhalt des Arrays darin sehen. Die declare -p
ermöglicht es Ihnen, den Inhalt des Arrays darin mit jedem Befehlsparameter in separaten Indizes anzuzeigen. Wenn ein solches Argument Leerzeichen enthält, verhindert das Anführungszeichen beim Hinzufügen zum Array, dass es aufgrund von Word-Splitting geteilt wird.
declare -p cmdArgs
declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")'
und führen Sie die Befehle als
aus"${cmdArgs[@]}"
23:15:18
(oder) insgesamt einen bash
verwenden Funktion zum Ausführen des Befehls,
cmd() {
date '+%H:%M:%S'
}
und rufen Sie die Funktion einfach auf
cmd
POSIX sh
hat keine Arrays, so dass Sie am ehesten kommen können, wenn Sie eine Liste von Elementen in den Positionsparametern erstellen. Hier ist ein POSIX sh
Möglichkeit, ein E-Mail-Programm auszuführen
# POSIX sh
# Usage: sendto subject address [address ...]
sendto() {
subject=$1
shift
first=1
for addr; do
if [ "$first" = 1 ]; then set --; first=0; fi
set -- "[email protected]" --recipient="$addr"
done
if [ "$first" = 1 ]; then
echo "usage: sendto subject address [address ...]"
return 1
fi
MailTool --subject="$subject" "[email protected]"
}
Beachten Sie, dass dieser Ansatz nur einfache Befehle ohne Umleitungen verarbeiten kann. Es kann keine Umleitungen, Pipelines, for/while-Schleifen, if-Anweisungen usw. verarbeiten
Ein weiterer häufiger Anwendungsfall ist die Ausführung von curl
mit mehreren Header-Feldern und Payload. Sie können immer Argumente wie unten definieren und curl
aufrufen auf dem erweiterten Array-Inhalt
curlArgs=('-H' "keyheader: value" '-H' "2ndkeyheader: 2ndvalue")
curl "${curlArgs[@]}"
Ein weiteres Beispiel,
payload='{}'
hostURL='http://google.com'
authToken='someToken'
authHeader='Authorization:Bearer "'"$authToken"'"'
Nun, da die Variablen definiert sind, verwenden Sie ein Array, um Ihre Befehlsargumente zu speichern
curlCMD=(-X POST "$hostURL" --data "$payload" -H "Content-Type:application/json" -H "$authHeader")
und führe jetzt eine ordnungsgemäße Erweiterung in Anführungszeichen durch
curl "${curlCMD[@]}"
var=$(echo "asdf")
echo $var
# => asdf
Bei dieser Methode wird der Befehl sofort ausgewertet und sein Rückgabewert gespeichert.
stored_date=$(date)
echo $stored_date
# => Thu Jan 15 10:57:16 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 10:57:16 EST 2015
Dasselbe gilt für Backtick
stored_date=`date`
echo $stored_date
# => Thu Jan 15 11:02:19 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 11:02:19 EST 2015
Verwendung von eval im $(...)
wird später nicht ausgewertet
stored_date=$(eval "date")
echo $stored_date
# => Thu Jan 15 11:05:30 EST 2015
# (wait a few seconds)
echo $stored_date
# => Thu Jan 15 11:05:30 EST 2015
Mit eval wird ausgewertet, wenn eval
verwendet wird
stored_date="date" # < storing the command itself
echo $(eval "$stored_date")
# => Thu Jan 15 11:07:05 EST 2015
# (wait a few seconds)
echo $(eval "$stored_date")
# => Thu Jan 15 11:07:16 EST 2015
# ^^ Time changed
Wenn Sie im obigen Beispiel einen Befehl mit Argumenten ausführen müssen, fügen Sie diese in die Zeichenfolge ein, die Sie speichern
stored_date="date -u"
# ...
Für Bash-Skripte ist dies selten relevant, aber eine letzte Anmerkung. Seien Sie vorsichtig mit eval
. Werten Sie nur Zeichenfolgen aus, die Sie kontrollieren, niemals Zeichenfolgen, die von einem nicht vertrauenswürdigen Benutzer stammen oder aus nicht vertrauenswürdigen Benutzereingaben erstellt wurden.
- Danke an @CharlesDuffy für die Erinnerung, den Befehl zu zitieren!