GNU/Linux >> Tutoriales Linux >  >> Linux

¿Cómo almacenar un comando en una variable en un script de shell?

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!

Linux
  1. ¿Almacenar la salida del comando en la variable de Shell?

  2. ¿Cómo obtener la dirección IP propia y guardarla en una variable en un script de Shell?

  3. ¿Cómo manejar los interruptores en un script de Shell?

  4. ¿Cómo aplazar la expansión variable?

  5. ¿Cómo saber si la salida de un comando o script de Shell es Stdout o Stderr?

Cómo ejecutar el comando / secuencia de comandos de Linux Shell en segundo plano

Cómo usar variables en secuencias de comandos de Shell

Cómo ejecutar un comando de Shell con Python

Cómo crear scripts de shell

Cómo almacenar un comando de Linux como una variable en el script de Shell

¿Cómo ejecutar un comando en un script de Shell?