Utiliser eval :
x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"
Ne pas utilisez eval
! Il présente un risque majeur d'introduire l'exécution de code arbitraire.
BashFAQ-50 - J'essaie de mettre une commande dans une variable, mais les cas complexes échouent toujours.
Mettez-le dans un tableau et développez tous les mots avec des guillemets doubles "${arr[@]}"
à pas laissez le IFS
diviser les mots en raison du fractionnement de mots.
cmdArgs=()
cmdArgs=('date' '+%H:%M:%S')
et voir le contenu du tableau à l'intérieur. Le declare -p
vous permet de voir le contenu du tableau à l'intérieur avec chaque paramètre de commande dans des index séparés. Si l'un de ces arguments contient des espaces, la citation à l'intérieur lors de l'ajout au tableau l'empêchera d'être divisé en raison du fractionnement de mots.
declare -p cmdArgs
declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")'
et exécutez les commandes comme
"${cmdArgs[@]}"
23:15:18
(ou) utiliser en tout un bash
fonction pour exécuter la commande,
cmd() {
date '+%H:%M:%S'
}
et appelez la fonction simplement
cmd
POSIX sh
n'a pas de tableaux, donc le plus proche que vous pouvez faire est de construire une liste d'éléments dans les paramètres positionnels. Voici un POSIX sh
façon d'exécuter un programme de messagerie
# 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]"
}
Notez que cette approche ne peut gérer que des commandes simples sans redirections. Il ne peut pas gérer les redirections, les pipelines, les boucles for/while, les instructions if, etc.
Un autre cas d'utilisation courant est lors de l'exécution de curl
avec plusieurs champs d'en-tête et charge utile. Vous pouvez toujours définir des arguments comme ci-dessous et invoquer curl
sur le contenu du tableau étendu
curlArgs=('-H' "keyheader: value" '-H' "2ndkeyheader: 2ndvalue")
curl "${curlArgs[@]}"
Un autre exemple,
payload='{}'
hostURL='http://google.com'
authToken='someToken'
authHeader='Authorization:Bearer "'"$authToken"'"'
maintenant que les variables sont définies, utilisez un tableau pour stocker vos arguments de commande
curlCMD=(-X POST "$hostURL" --data "$payload" -H "Content-Type:application/json" -H "$authHeader")
et maintenant faites une expansion entre guillemets appropriée
curl "${curlCMD[@]}"
var=$(echo "asdf")
echo $var
# => asdf
En utilisant cette méthode, la commande est immédiatement évaluée et sa valeur de retour est stockée.
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
Idem avec 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
Utiliser eval dans le $(...)
ne le fera pas évaluer plus tard
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
En utilisant eval, il est évalué lorsque eval
est utilisé
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
Dans l'exemple ci-dessus, si vous devez exécuter une commande avec des arguments, placez-les dans la chaîne que vous stockez
stored_date="date -u"
# ...
Pour les scripts bash, cela est rarement pertinent, mais une dernière note. Soyez prudent avec eval
. N'évaluez que les chaînes que vous contrôlez, jamais les chaînes provenant d'un utilisateur non approuvé ou créées à partir d'entrées d'utilisateur non approuvées.
- Merci à @CharlesDuffy de m'avoir rappelé de citer la commande !