Usar evaluación:
x="ls | wc"
eval "$x"
y=$(eval "$x")
echo "$y"
no usa eval
! Tiene un gran riesgo de introducir la ejecución de código arbitrario.
BashFAQ-50:intento poner un comando en una variable, pero los casos complejos siempre fallan.
Póngalo en una matriz y expanda todas las palabras con comillas dobles "${arr[@]}"
a no deja que el IFS
dividir las palabras debido a la división de palabras.
cmdArgs=()
cmdArgs=('date' '+%H:%M:%S')
y ver el contenido de la matriz en el interior. El declare -p
le permite ver el contenido de la matriz en el interior con cada parámetro de comando en índices separados. Si uno de esos argumentos contiene espacios, citar adentro mientras se agrega a la matriz evitará que se divida debido a la división de palabras.
declare -p cmdArgs
declare -a cmdArgs='([0]="date" [1]="+%H:%M:%S")'
y ejecutar los comandos como
"${cmdArgs[@]}"
23:15:18
(o) en conjunto use un bash
función para ejecutar el comando,
cmd() {
date '+%H:%M:%S'
}
y llamar a la función como simplemente
cmd
POSIX sh
no tiene matrices, por lo que lo más cerca que puede llegar es construir una lista de elementos en los parámetros posicionales. Aquí hay un POSIX sh
forma de ejecutar un programa de correo
# 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]"
}
Tenga en cuenta que este enfoque solo puede manejar comandos simples sin redirecciones. No puede manejar redirecciones, canalizaciones, bucles for/while, declaraciones if, etc.
Otro caso de uso común es cuando se ejecuta curl
con múltiples campos de encabezado y carga útil. Siempre puede definir argumentos como a continuación e invocar curl
en el contenido de la matriz expandida
curlArgs=('-H' "keyheader: value" '-H' "2ndkeyheader: 2ndvalue")
curl "${curlArgs[@]}"
Otro ejemplo,
payload='{}'
hostURL='http://google.com'
authToken='someToken'
authHeader='Authorization:Bearer "'"$authToken"'"'
ahora que las variables están definidas, use una matriz para almacenar sus argumentos de comando
curlCMD=(-X POST "$hostURL" --data "$payload" -H "Content-Type:application/json" -H "$authHeader")
y ahora haz una expansión entre comillas adecuada
curl "${curlCMD[@]}"
var=$(echo "asdf")
echo $var
# => asdf
Con este método, el comando se evalúa inmediatamente y se almacena su valor de retorno.
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
Lo mismo con el acento grave
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
Usando eval en el $(...)
no hará que se evalúe más tarde
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
Usando eval, se evalúa cuando eval
se usa
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
En el ejemplo anterior, si necesita ejecutar un comando con argumentos, colóquelos en la cadena que está almacenando
stored_date="date -u"
# ...
Para los scripts de bash, esto rara vez es relevante, pero una última nota. Cuidado con eval
. Evalúa solo las cadenas que controlas, nunca las cadenas que provengan de un usuario que no sea de confianza o creadas a partir de la entrada de un usuario que no sea de confianza.
- ¡Gracias a @CharlesDuffy por recordarme citar el comando!