¿Cuál es la forma correcta de llamar a algún comando almacenado en una variable?
¿Hay alguna diferencia entre 1 y 2?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
shell
unix
parameter-expansion
Volodymyr Bezuglyy
fuente
fuente
Respuestas:
Los shells de Unix operan una serie de transformaciones en cada línea de entrada antes de ejecutarlas. Para la mayoría de los shells, se parece a esto (tomado de la página de
bash
manual):El uso
$cmd
directo lo reemplaza por su comando durante la fase de expansión de parámetros, y luego se somete a todas las transformaciones siguientes.El uso
eval "$cmd"
no hace nada hasta la fase de eliminación de la cotización, donde$cmd
se devuelve como está y se pasa como un parámetro aeval
, cuya función es ejecutar toda la cadena nuevamente antes de ejecutar.Entonces, básicamente, son iguales en la mayoría de los casos y difieren cuando su comando hace uso de los pasos de transformación hasta la expansión de parámetros. Por ejemplo, usando la expansión de llaves:
$ cmd="echo foo{bar,baz}" $ $cmd foo{bar,baz} $ eval "$cmd" foobar foobaz
fuente
eval "$cmd"
sin escribireval
?$($cmd)
?${$cmd}
?eval
operación analiza los datos como sintaxis; por lo tanto, es muy sensible a la seguridad, y hacerlo implícitamente sería de muy mala forma.Si simplemente lo hacemos
eval $cmd
cuando lo hacemoscmd="ls -l"
(de forma interactiva y en un script) obtenemos el resultado deseado. En su caso, tiene una tubería con un grep sin un patrón, por lo que la parte grep fallará con un mensaje de error. Solo$cmd
generará un mensaje de "comando no encontrado" (o algo así). Así que intente usar eval y use un comando terminado, no uno que genere un mensaje de error.fuente
$cmd
simplemente reemplazaría la variable con su valor para ser ejecutado en la línea de comando.eval "$cmd"
hace expansión de variables y sustitución de comandos antes de ejecutar el valor resultante en la línea de comandosEl segundo método es útil cuando desea ejecutar comandos que no son flexibles, por ejemplo.
for i in {$a..$b}
El bucle de formato no funcionará porque no permite variables.
En este caso, una tubería a bash o eval es una solución.
Probado en Mac OSX 10.6.8, Bash 3.2.48
fuente
Creo que deberías poner
(comillas invertidas) símbolos alrededor de su variable.
fuente