2010-02-23 5 views
12

¿Puede proporcionar algún ejemplo en el que sea realmente necesario usar eval EXPR? Lo pregunto porque, en general, lo desanima.¿Hay algún caso de uso donde la evaluación de cadena sea necesaria en Perl?

+0

¿Por qué esto -1'd? –

+0

No es un duplicado, hay muchos usos de eval que son específicos de Perl 5, mientras que el hilo de referencia analiza el concepto general de evaluación de código de tiempo de ejecución – willert

+0

@willert Gracias por señalar mi error. Estoy seguro de que hemos discutido este tema antes, pero estoy teniendo problemas para encontrarlo. –

Respuesta

0

Hace algunos años, escribí un generador de sitios web estáticos que usaba Perl (< - interesante que mi corrector ortográfico sugiere "Peril" como un reemplazo para eso) como su lenguaje de scripting. Permitió al usuario ingresar información sobre diferentes niveles de una jerarquía: el primero en comercializar era un cementerio en el que tenía clientes (clientes de pago) que poseían monumentos conmemorativos (para los difuntos, obviamente).

Tenía una interfaz gráfica de usuario en la que entró variables tales como (temblor en mis habilidades gráficas aquí):

+------------+----------------------------+ 
| ClientName | Pax Diablo     | 
+------------+----------------------------+ 
| Address | 666 Hades St, Washinton DC | 
+------------+----------------------------+ 

y variables de imagen también.

Además, para cada mercado (como el cementerio antes mencionado), había un script de control que básicamente ejecutaba y procesaba cada registro en múltiples niveles de jerarquía para generar el contenido estático. Antes de eso, el programa se había convertido todas esas variables en cosas como:

$Var{"ClientName"} = "Pax Diablo"; 

(creo que la sintaxis es correcta, no he hecho ningún desarrollo Perl por un tiempo). El resultado final fue un sitio web completo con muchos clientes, muchos memoriales, páginas de búsqueda y un pequeño y generoso dinero mientras duró (los directores de funerarias me sacaron del mercado y ofrecieron lo mismo que un servicio "gratuito" dentro sus paquetes regulares).

Pero todo esto fue básicamente escrito en Perl mínima que sólo hizo dos cosas:

  • convirtió a los variables en instrucciones de asignación de Perl; y
  • ejecutaron el código de Perl específico del mercado.

Tanto la ejecución de las instrucciones de asignación como el código de Perl específico del mercado se realizaron con eval.

Así que no es tan inútil como pueda pensar. Era una forma barata de introducir scripts en una aplicación.

+2

Realmente, realmente no creo que la configuración de carga es una muy buena evaluación –

+0

Esa es una cuestión de opinión. La configuración permitida por el usuario eran las variables estrechamente controladas que se verificaron minuciosamente para detectar ataques de inyección. La parte no revisada era el código específico del mercado que fue escrito por el desarrollador de todos modos, así que no hay peligro allí. En general, funcionó bastante bien. Ahora no dejaría que un usuario escriba en frases como "$ x = 7;" y evalúelos alocadamente: creo que eso es a lo que te referías. – paxdiablo

5

String eval es la única forma de crear código nuevo de cadenas. Esto rara vez es necesario, pero existen algunos casos de uso válidos, por ejemplo, al convertir plantillas en código ejecutable. Aparte de eso, hay muy pocos usos válidos para eso. eval "require $module_name" es una expresión idiomática bien conocida, pero usar por ejemplo Module::Load es una idea mejor que esa IMO.

+4

Solo como explicación: eval "require $ module_name" es necesario en lugar de "eval {require $ module_name}" porque "require EXPR" intenta requerir un archivo mientras "require BAREWORD" (es decir, el sting evaluado en este eval) requiere un módulo . – willert

4

eval EXPR se puede utilizar para el meta-programación en caso de que no se puede confiar en Moose o similares marcos para crear clases sobre la marcha. Eche un vistazo a la fuente de Exception::Class para ver el horror completo de esta técnica.

Adición: (@friedo)
Una característica que proporciona eval sobre la manipulación tabla de símbolos es la capacidad de utilizar Super para que funcionen como se esperaba:

package Foo; 
sub msg { return 'Foo' } 

package MyCodeGenerator; 

use strict; 
use warnings; 

eval <<'EOPERL'; # '' -> no variable interpolation 
    package FooBar; 
    @FooBar::ISA = qw/Foo/; 
    sub msg { 
    my $self = shift; 
    return $self->SUPER::msg() . 'Bar'; # calls &Foo::msg 
    } 
EOPERL 

Si bien esto (con suerte) morir durante el tiempo de ejecución, o te prepara para una larga sesión de depuración horas :

package BROKEN_Generator; 

@FooBar::ISA = qw/Foo/; 
*{'FooBar::msg'} = sub { 
    my $self = shift; 
    return $self->SUPER::msg() . 'Bar'; # tries to call &BROKEN_Generator::msg 
} 

fácilmente en mi Top 5 of things I hate about Perl!

+0

Generalmente no hay necesidad de usar 'eval' para compilar clases dinámicamente; usted puede ensuciar con la tabla de símbolos. Sin embargo, me sorprendió ver esos 'eval's en Exception :: Class. Me pregunto si alguno de ellos es realmente necesario ... – friedo

+1

Las declaraciones eval son necesarias porque Exception :: Class se basa en llamadas SUPER en una jerarquía de clases creada dinámicamente. SUPER está vinculado a la @ISA del paquete actual, por lo que no puede llamarlo desde subs anónimos y la manipulación de la tabla de símbolos ingenua se cae. Podrías evitar esto, pero no es nada fácil y IIRC no tenía una alternativa preempaquetada en 2000 cuando se inició E :: C. – willert

+1

Hay NEXT (search.cpan.org/perldoc?NEXT) para eso (aunque probablemente no existía en 2000). –

6

eval cuerdas es la única forma de:

  1. ejecutar código nuevo en un paquete de tiempo de ejecución decidido
  2. complemento sobrecargar a un paquete en tiempo de ejecución (al menos según overload.pm)
  3. ejecución arbitraria cuerdas de Perl
  4. compilar tipo sustituciones macro

eval cadena no debe ser usado para:

  1. evaluar referencias simbólicas
  2. ejecutar ningún código del usuario
  3. atrapar errores
  4. si hay alguna otra manera de hacerlo

eval también se puede utilizar para crear ad- protocolos de comunicación hoc entre diferentes sistemas o diferentes idiomas que también tienen eval (siempre que todo sea seguro, por supuesto). JSON se puede ver como un subconjunto más seguro, pero limitado de este método)

Cuestiones relacionadas