Utilícelo type commandpara saber de qué tipo es un comando . ( type evalen este caso)
rozcietrzewiacz
99
"eval is an shell builtin"
Nuno Rafael Figueiredo
3
help evalobtener la página "man" de su shell
m-ric
eval es un bash-builtin y está documentado en la página del manual de bash. Así que simplemente escriba "man bash" y busque la sección apropiada para eval. Esto también se aplica a otras bash-builtins.
Dirk Thannhäuser
Respuestas:
132
evalEs parte de POSIX. Es una interfaz que puede ser un shell incorporado.
En la primera línea se define $foocon el valor '10'y $xcon el valor 'foo'.
Ahora defina $y, que consiste en la cadena '$foo'. El signo de dólar se debe escapar con '$'.
Para verificar el resultado echo $y,.
El resultado será la cadena. '$foo'
Ahora repetimos la tarea con eval. Primero evaluará $xa la cadena 'foo'. Ahora tenemos la declaración y=$fooque será evaluada y=10.
El resultado de echo $yahora es el valor '10'.
Esta es una función común en muchos idiomas, por ejemplo, Perl y JavaScript. Eche un vistazo a perldoc eval para obtener más ejemplos: http://perldoc.perl.org/functions/eval.html
En terminología de shell, evales una función incorporada, no una función. En la práctica, las funciones incorporadas se comportan de manera muy similar a las funciones que no tienen una definición en el lenguaje, pero no del todo (como se hace evidente si está lo suficientemente retorcido como para definir una función llamada eval).
Gilles
gracias, arreglado eso :-)
echox
44
¿Cuál es la diferencia entre eval y backticks '?
JohnyTex
55
Los backticks son una forma abreviada de ejecutar otro shell completo, lo que significa que tendrás otro proceso bash / sh secundario ejecutándose dentro de tu script.
Aaron R.
¿Por qué echo $ y (etapa 3) trae foo (10) en lugar de $ foo? (es decir, solo el valor de foo en lugar de la cadena $ + el valor de foo)?
JohnDoea
60
Sí, evales un comando interno de bash, por lo que se describe en la bashpágina de manual.
eval[arg ...]The args are read and concatenated together into a single com-
mand.This command is then read and executed by the shell, and
its exit status is returned as the value of eval.If there are
no args, or only null arguments,eval returns 0.
Por lo general, se usa en combinación con una sustitución de comando . Sin un explícito eval, el shell intenta ejecutar el resultado de una sustitución de comando, no evaluarlo .
Digamos que desea codificar un equivalente de VAR=value; echo $VAR. Tenga en cuenta la diferencia en cómo el shell maneja los escritos de echo VAR=value:
andcoz@...:~> $( echo VAR=value )
bash: VAR=value: command not found
andcoz@...:~> echo $VAR
<empty line>
El shell intenta ejecutarse echoy VAR=valuecomo dos comandos separados. Lanza un error sobre la segunda cadena. La asignación sigue siendo ineficaz.
andcoz@...:~>eval $( echo VAR=value )
andcoz@...:~> echo $VAR
value
El shell fusiona (concatena) las dos cadenas echoy VAR=valueanaliza esta unidad individual de acuerdo con las reglas apropiadas y la ejecuta.
Por último, pero no menos importante, evalpuede ser un comando muy peligroso. Cualquier entrada a un evalcomando debe verificarse cuidadosamente para evitar problemas de seguridad.
evalno tiene página de manual porque no es un comando externo separado, sino un shell incorporado, lo que significa un comando interno y conocido solo por el shell ( bash). La parte relevante de la bashpágina del manual dice:
eval[arg ...]The args are read and concatenated together into a single command.This command is then read and executed by the shell, and its exit
status is returned as the value of eval.If there are no args, or only
null arguments,eval returns 0
Además, la salida si help evales:
eval:eval[arg ...]Execute arguments as a shell command.CombineARGs into a single string, use the result as input to the shell,
and execute the resulting commands.ExitStatus:Returns exit status of command or success if command is null.
evales un comando poderoso y si tiene la intención de usarlo, debe tener mucho cuidado para evitar los posibles riesgos de seguridad que conlleva.
La instrucción eval le dice al shell que tome los argumentos de eval como comando y los ejecute a través de la línea de comandos. Es útil en una situación como la siguiente:
En su script, si está definiendo un comando en una variable y luego desea usar ese comando, entonces debe usar eval:
/home/user1 > a="ls | more"/home/user1 > $a
bash: command not found: ls | more
/home/user1 ># Above command didn't work as ls tried to list file with name pipe (|) and more. But these files are not there/home/user1 >eval $a
file.txt
mailids
remote_cmd.sh
sample.txt
tmp
/home/user1 >
El comentario en la línea 4 de su ejemplo es incorrecto: debería ser "El comando anterior no funcionó porque bash intentó encontrar un comando llamado ls | more. En otras palabras: el nombre del comando único constaba de nueve caracteres, incluidos los espacios y el símbolo de la tubería .
cfi
Tengo exactamente el mismo comportamiento que informó. bash --version == GNU bash, versión 3.2.57 (1) -release (x86_64-apple-darwin18)
Alexander Bird
10
¿Qué es eval?
eval es un comando de shell que generalmente se implementa como incorporado.
El término "incorporado" implica que el shell puede ejecutar la utilidad directamente y no necesita buscarla.
¿Qué hace?
En términos simples: hace que una línea de entrada se analice dos veces .
¿Como hace eso?
El shell tiene una secuencia de pasos que sigue para "procesar" una línea. Podrías mirar esta imagen y darte cuenta de que eval es la única línea que sube, de vuelta al paso 1, a la izquierda. De la descripción POSIX :
2.1 Introducción de Shell
El shell lee su entrada ...
El shell divide la entrada en tokens: palabras y operadores.
El shell analiza la entrada en comandos simples y compuestos.
El shell realiza varias expansiones (por separado) ...
El shell realiza la redirección y elimina los operadores de redirección y sus operandos de la lista de parámetros.
El shell ejecuta una función, un archivo ejecutable incorporado o un script ...
El shell opcionalmente espera a que se complete el comando y recopila el estado de salida.
En el paso 6 se ejecutará un incorporado.
En el paso 6 eval hace que la línea procesada se envíe de vuelta al paso 1.
Es la única condición bajo la cual la secuencia de ejecución retrocede.
Por eso digo: con eval, una línea de entrada se analiza dos veces .
Efectos del análisis dos veces.
El primero.
Y efecto más importante para entender. Es esa una consecuencia de la primera vez que una línea está sujeta a los siete pasos de shell que se muestran arriba, es la cita . Dentro del paso 4 (expansiones), también hay una secuencia de pasos para realizar todas las expansiones , la última de las cuales es Quitar eliminación :
La eliminación de la cotización siempre se realizará en último lugar.
Entonces, siempre, hay un nivel de cita eliminado.
Segundo.
Como consecuencia de ese primer efecto, partes adicionales / diferentes de la línea quedan expuestas al análisis del shell y a todos los demás pasos.
Ejemplo.
Indirección
Eso permite ejecutar expansiones indirectas:
a=b b=c ;eval echo \$$a ### shall produce "c"
¿Por qué? Porque en el primer bucle, $se cita el primero .
Como tal, el shell lo ignora para las expansiones.
El siguiente $con el nombre a se expande para producir "b".
Luego, se elimina un nivel de $comillas , lo que hace que la primera no se cite.
Fin del primer ciclo.
Es entonces, en el segundo bucle que $bel shell lee la cadena .
Luego se expandió a "c"
y se dio como argumento para echo.
Para "ver" qué eval producirá en el primer bucle (para ser evaluado nuevamente), use echo. O cualquier comando / script / programa que muestre claramente los argumentos:
$ a=b b=c
$ eval echo \$$a;
c
Reemplace eval por echo para "ver" lo que está sucediendo:
$ echo echo \$$a
echo $b
También es posible mostrar todas las "partes" de una línea con:
$ printf '<%s> ' echo \$$a
<echo><$b>
Que, en este ejemplo, es solo un eco y una variable, pero recuérdelo para ayudar a evaluar casos más complejos.
Una corrección
Hay que decir que: hay un error en el código anterior, ¿puedes verlo?
Fácil: faltan algunas citas.
¿Cómo? Tu puedes preguntar. Simple, cambiemos las variables (no el código):
$ a=b b="hi jk"
$ eval echo \$$a
hi jk
¿Ves los espacios faltantes?
Eso es porque el valor en el interior $bfue dividido por el shell.
Si eso no te convence, prueba esto:
$ a=b b="hi * jk"
$ eval echo \$$a ### warning this will expand to the list ### of all files in the present directory.
¿Por qué?
Faltan citas. Para que funcione correctamente (agregue comillas internas "$a"y externas \").
Prueba esto (es perfectamente seguro):
$ a=b b="hi * jk"
$ eval echo \" \$"$a" \"
hi * jk
Sobre el manual:
No hay página de manual para ello.
No, no hay una página de manual independiente para esto. La búsqueda de manual con man -f evalo incluso apropos evalno muestra ninguna entrada.
Está incluido en el interior man bash. Como es cualquier incorporado.
Busque "SHELL BUILTIN COMMANDS" y luego "eval".
Una forma más fácil de obtener ayuda es: en bash, puede hacer help evalpara ver la ayuda para el incorporado.
¿Por qué eval se llama malvado?
Porque es vinculante el texto para codificar dinámicamente.
En otras palabras: convierte la lista de sus argumentos (y / o expansiones de tales argumentos) en una línea ejecutada. Si por algún motivo, un atacante ha establecido un argumento, estará ejecutando el código del atacante.
O incluso más simple, con eval le está diciendo a quien haya definido el valor de uno o varios argumentos:
Vamos, siéntate aquí y escribe cualquier línea de comando, la ejecutaré con mis poderes.
¿Eso es peligroso? Debe quedar claro para todos que lo es.
La regla de seguridad para eval debe ser:
Ejecutar eval solo en variables a las que le haya dado su valor.
evalEs una característica de los idiomas más interpretadas ( TCL, python, ruby...), no sólo las conchas. Se utiliza para evaluar el código dinámicamente.
En shells, se implementa como un comando incorporado de shell.
Básicamente, evaltoma una cadena como argumento y evalúa / interpreta el código que contiene. En shells, evalpuede tomar más de un argumento, pero evalsolo los concatena para formar la cadena para evaluar.
Es muy poderoso porque puedes construir código dinámicamente y ejecutarlo, algo que no puedes hacer en lenguajes compilados como C.
Me gusta:
varname=$1 varvalue=$2
eval"$varname=\$varvalue"# evaluate a string like "foo=$varvalue"# which in Bourne-like shell language# is a variable assignment.
Pero también es peligroso, ya que es importante desinfectar las partes dinámicas (proporcionadas externamente) de lo que se pasa evalpor la misma razón por la que se interpreta como código shell.
Por ejemplo, arriba si $1es evil-command; var, evalterminaría evaluando el evil-command; var=$varvaluecódigo de shell y luego lo ejecutaría evil-command.
La maldad de a evalmenudo es exagerada.
OK, es peligroso, pero al menos sabemos que es peligroso.
Una gran cantidad de otros comandos evaluará código shell en sus argumentos si no se limpia, al igual que (dependiendo de la cáscara), [aka test, export, printf, GNU sed, awky, por supuesto sh/ bash/ perly todos los intérpretes ...
Ejemplos (aquí usando unamecomo evil-commandy $acomo datos no desinfectados proporcionados externamente):
Esos sed, export... los comandos podrían considerarse más peligrosos porque, aunque es obvio, eval "$var"hará que el contenido $varsea evaluado como código shell, no es tan obvio con sed "s/foo/$var/"o export "$var=value"o [ "$var" -gt 0 ]. El peligro es el mismo, pero está oculto en esos otros comandos.
@BinaryZebra, sedcomo evalse le está pasando una cadena contenida en una variable, y para ambos, el contenido de esa cadena termina siendo evaluado como código de shell, por lo que sedes tan peligroso como eval, eso es lo que estoy diciendo. sedse le pasa una cadena que contiene uname(uname no se ha ejecutado hasta ahora) y mediante la invocación de sed, el comando uname termina ejecutándose. Me gusta para eval. En sed 's/foo/$a/g', no estás pasando datos no desinfectados sed, eso no es de lo que estamos hablando aquí.
Gracias por su contribución, pero, por divertidos que sean, no estamos realmente interesados en compilar una lista de ejemplos (ligeramente diferentes) de uso eval. ¿Cree que hay algún aspecto fundamental y crítico de la funcionalidad evalque no está cubierto en las respuestas existentes? Si es así, explíquelo y use el ejemplo para ilustrar su explicación. Por favor no responda en los comentarios; edite su respuesta para que sea más clara y completa.
type command
para saber de qué tipo es un comando . (type eval
en este caso)help eval
obtener la página "man" de su shellRespuestas:
eval
Es parte de POSIX. Es una interfaz que puede ser un shell incorporado.Se describe en el "Manual del programador POSIX": http://www.unix.com/man-page/posix/1posix/eval/
Tomará un argumento y construirá un comando del mismo, que será ejecutado por el shell. Este es el ejemplo de la página de manual:
$foo
con el valor'10'
y$x
con el valor'foo'
.$y
, que consiste en la cadena'$foo'
. El signo de dólar se debe escapar con'$'
.echo $y
,.'$foo'
eval
. Primero evaluará$x
a la cadena'foo'
. Ahora tenemos la declaracióny=$foo
que será evaluaday=10
.echo $y
ahora es el valor'10'
.Esta es una función común en muchos idiomas, por ejemplo, Perl y JavaScript. Eche un vistazo a perldoc eval para obtener más ejemplos: http://perldoc.perl.org/functions/eval.html
fuente
eval
es una función incorporada, no una función. En la práctica, las funciones incorporadas se comportan de manera muy similar a las funciones que no tienen una definición en el lenguaje, pero no del todo (como se hace evidente si está lo suficientemente retorcido como para definir una función llamadaeval
).Sí,
eval
es un comando interno de bash, por lo que se describe en labash
página de manual.Por lo general, se usa en combinación con una sustitución de comando . Sin un explícito
eval
, el shell intenta ejecutar el resultado de una sustitución de comando, no evaluarlo .Digamos que desea codificar un equivalente de
VAR=value; echo $VAR
. Tenga en cuenta la diferencia en cómo el shell maneja los escritos deecho VAR=value
:El shell intenta ejecutarse
echo
yVAR=value
como dos comandos separados. Lanza un error sobre la segunda cadena. La asignación sigue siendo ineficaz.echo
yVAR=value
analiza esta unidad individual de acuerdo con las reglas apropiadas y la ejecuta.Por último, pero no menos importante,
eval
puede ser un comando muy peligroso. Cualquier entrada a uneval
comando debe verificarse cuidadosamente para evitar problemas de seguridad.fuente
eval
no tiene página de manual porque no es un comando externo separado, sino un shell incorporado, lo que significa un comando interno y conocido solo por el shell (bash
). La parte relevante de labash
página del manual dice:Además, la salida si
help eval
es:eval
es un comando poderoso y si tiene la intención de usarlo, debe tener mucho cuidado para evitar los posibles riesgos de seguridad que conlleva.fuente
La instrucción eval le dice al shell que tome los argumentos de eval como comando y los ejecute a través de la línea de comandos. Es útil en una situación como la siguiente:
En su script, si está definiendo un comando en una variable y luego desea usar ese comando, entonces debe usar eval:
fuente
ls | more
. En otras palabras: el nombre del comando único constaba de nueve caracteres, incluidos los espacios y el símbolo de la tubería .¿Qué es eval?
eval es un comando de shell que generalmente se implementa como incorporado.
En POSIX aparece como parte de "2.14. Utilidades especiales incorporadas" en la entrada "eval" .
Lo que significa construir es:
¿Qué hace?
En términos simples: hace que una línea de entrada se analice dos veces .
¿Como hace eso?
El shell tiene una secuencia de pasos que sigue para "procesar" una línea. Podrías mirar esta imagen y darte cuenta de que eval es la única línea que sube, de vuelta al paso 1, a la izquierda. De la descripción POSIX :
En el paso 6 se ejecutará un incorporado.
En el paso 6 eval hace que la línea procesada se envíe de vuelta al paso 1.
Es la única condición bajo la cual la secuencia de ejecución retrocede.
Efectos del análisis dos veces.
El primero.
Y efecto más importante para entender. Es esa una consecuencia de la primera vez que una línea está sujeta a los siete pasos de shell que se muestran arriba, es la cita . Dentro del paso 4 (expansiones), también hay una secuencia de pasos para realizar todas las expansiones , la última de las cuales es Quitar eliminación :
Entonces, siempre, hay un nivel de cita eliminado.
Segundo.
Como consecuencia de ese primer efecto, partes adicionales / diferentes de la línea quedan expuestas al análisis del shell y a todos los demás pasos.
Ejemplo.
Indirección
Eso permite ejecutar expansiones indirectas:
¿Por qué? Porque en el primer bucle,
$
se cita el primero .Como tal, el shell lo ignora para las expansiones.
El siguiente
$
con el nombre a se expande para producir "b".Luego, se elimina un nivel de
$
comillas , lo que hace que la primera no se cite.Fin del primer ciclo.
Es entonces, en el segundo bucle que
$b
el shell lee la cadena .Luego se expandió a "c"
y se dio como argumento para
echo
.Para "ver" qué eval producirá en el primer bucle (para ser evaluado nuevamente), use echo. O cualquier comando / script / programa que muestre claramente los argumentos:
Reemplace eval por echo para "ver" lo que está sucediendo:
También es posible mostrar todas las "partes" de una línea con:
Que, en este ejemplo, es solo un eco y una variable, pero recuérdelo para ayudar a evaluar casos más complejos.
Una corrección
Hay que decir que: hay un error en el código anterior, ¿puedes verlo?
Fácil: faltan algunas citas.
¿Cómo? Tu puedes preguntar. Simple, cambiemos las variables (no el código):
¿Ves los espacios faltantes?
Eso es porque el valor en el interior
$b
fue dividido por el shell.Si eso no te convence, prueba esto:
¿Por qué?
Faltan citas. Para que funcione correctamente (agregue comillas internas
"$a"
y externas\"
).Prueba esto (es perfectamente seguro):
Sobre el manual:
No, no hay una página de manual independiente para esto. La búsqueda de manual con
man -f eval
o inclusoapropos eval
no muestra ninguna entrada.Está incluido en el interior
man bash
. Como es cualquier incorporado.Busque "SHELL BUILTIN COMMANDS" y luego "eval".
Una forma más fácil de obtener ayuda es: en bash, puede hacer
help eval
para ver la ayuda para el incorporado.¿Por qué eval se llama malvado?
Porque es vinculante el texto para codificar dinámicamente.
En otras palabras: convierte la lista de sus argumentos (y / o expansiones de tales argumentos) en una línea ejecutada. Si por algún motivo, un atacante ha establecido un argumento, estará ejecutando el código del atacante.
O incluso más simple, con eval le está diciendo a quien haya definido el valor de uno o varios argumentos:
¿Eso es peligroso? Debe quedar claro para todos que lo es.
La regla de seguridad para eval debe ser:
Ejecutar eval solo en variables a las que le haya dado su valor.
Lea más detalles aquí .
fuente
eval
Es una característica de los idiomas más interpretadas (TCL
,python
,ruby
...), no sólo las conchas. Se utiliza para evaluar el código dinámicamente.En shells, se implementa como un comando incorporado de shell.
Básicamente,
eval
toma una cadena como argumento y evalúa / interpreta el código que contiene. En shells,eval
puede tomar más de un argumento, peroeval
solo los concatena para formar la cadena para evaluar.Es muy poderoso porque puedes construir código dinámicamente y ejecutarlo, algo que no puedes hacer en lenguajes compilados como C.
Me gusta:
Pero también es peligroso, ya que es importante desinfectar las partes dinámicas (proporcionadas externamente) de lo que se pasa
eval
por la misma razón por la que se interpreta como código shell.Por ejemplo, arriba si
$1
esevil-command; var
,eval
terminaría evaluando elevil-command; var=$varvalue
código de shell y luego lo ejecutaríaevil-command
.La maldad de a
eval
menudo es exagerada.OK, es peligroso, pero al menos sabemos que es peligroso.
Una gran cantidad de otros comandos evaluará código shell en sus argumentos si no se limpia, al igual que (dependiendo de la cáscara),
[
akatest
,export
,printf
, GNUsed
,awk
y, por supuestosh
/bash
/perl
y todos los intérpretes ...Ejemplos (aquí usando
uname
comoevil-command
y$a
como datos no desinfectados proporcionados externamente):Esos
sed
,export
... los comandos podrían considerarse más peligrosos porque, aunque es obvio,eval "$var"
hará que el contenido$var
sea evaluado como código shell, no es tan obvio consed "s/foo/$var/"
oexport "$var=value"
o[ "$var" -gt 0 ]
. El peligro es el mismo, pero está oculto en esos otros comandos.fuente
sed
comoeval
se le está pasando una cadena contenida en una variable, y para ambos, el contenido de esa cadena termina siendo evaluado como código de shell, por lo quesed
es tan peligroso comoeval
, eso es lo que estoy diciendo.sed
se le pasa una cadena que contieneuname
(uname no se ha ejecutado hasta ahora) y mediante la invocación desed
, el comando uname termina ejecutándose. Me gusta para eval. Ensed 's/foo/$a/g'
, no estás pasando datos no desinfectadossed
, eso no es de lo que estamos hablando aquí.Este ejemplo puede arrojar algo de luz:
Salida del script anterior:
fuente
eval
. ¿Cree que hay algún aspecto fundamental y crítico de la funcionalidadeval
que no está cubierto en las respuestas existentes? Si es así, explíquelo y use el ejemplo para ilustrar su explicación. Por favor no responda en los comentarios; edite su respuesta para que sea más clara y completa.