¿Cómo ejecutar el comando almacenado en una variable?


Respuestas:


95

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 bashmanual):

  • división inicial de palabras
  • expansión del corsé
  • expansión de tilde
  • expansión de parámetros, variables y aritmética
  • sustitución de comando
  • división de palabras secundarias
  • expansión de ruta (también conocida como globbing)
  • eliminación de cotizaciones

El uso $cmddirecto 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 $cmdse devuelve como está y se pasa como un parámetro a eval, 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

6
¿Cómo hacerlo eval "$cmd"sin escribir eval? $($cmd)? ${$cmd}?
Steven Lu

2
@StevenLu, ninguno de ellos es equivalente, intencionalmente: una evaloperació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.
Charles Duffy

5

Si simplemente lo hacemos eval $cmd cuando lo hacemos cmd="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 $cmdgenerará 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.


Fue sólo un error de imprenta. Debería ser "excepción grep".
Volodymyr Bezuglyy

luego use eval, no $ cmd por sí mismo, ya que probablemente no funcionará (no lo hizo en mis pruebas, bajo bash y zsh). Esto es lo que estaba destinado a hacer eval ...
Henno Brandsma

0

$cmdsimplemente 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 comandos

El 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


-4

Creo que deberías poner

`

(comillas invertidas) símbolos alrededor de su variable.


4
Esto ejecuta la salida del comando, que por ejemplo, en el caso de ls -l generará un mensaje como "total" comando no encontrado "(porque total ... es parte de la salida de ls -l, por ejemplo). NO es lo que quieres.
Henno Brandsma
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.