2012-07-13 18 views
5

Tenemos en el trabajo un script de Perl que se utiliza para realizar tareas de mantenimiento. Necesitaba modificarlo para manejar más tareas. El problema es que el script está compilado y la fuente se perdió hace mucho tiempo.Perl: accediendo a 'mis' variables desde otro archivo

Intenté usar B :: Deparse para recrear el archivo pero Deparse no es perfecto y la salida está rota (y muy grande ~ 5000 líneas de código depuradas).

Después de leer el código depurador encontré que necesito modificar una función. El script compilado carga un módulo de script de texto plano, por lo que modifiqué el módulo para anular la función y realizar la tarea que necesito que realice. El problema ahora es que no puedo acceder al script principal "mis" variables.

He aquí un ejemplo:

# main.pl 

my $a = 1; 

sub call_me { 
    print "unmodified"; 
} 

use MOD; 

call_me; 


MOD.pm 
package MOD; 

main::{'call_me'} = sub { 
    print "\$main::a = $main::a\n"; 
} 

El resultado es: "$main::a =" en lugar de obtener el valor real.

Gracias de antemano.

+0

Las variables léxicas ('my') no aparecen en la tabla de símbolos del paquete en contraste con el paquete global. Así que este es un tema difícil, pero interesante ... # Nota: simplemente puede escribir sub main :: call_me {...} si no recuerdo mal. – amon

+0

¿Qué quiere decir con "script compilado". ¿Te refieres empaquetado? – ikegami

+0

Estoy de acuerdo con ikegami, puede haber alguna manera de recuperar ese script, pero para saber, necesitamos saber a qué te refieres con "compilado". –

Respuesta

8

La respuesta corta es que las variables declaradas con my no son accesibles fuera de su alcance léxico. Si no puede cambiar la declaración a "nuestro" (debido a la naturaleza "compilada" del guión original), todavía no ha perdido la buena suerte. Perl casi siempre proporciona una forma de evitar este tipo de cosas.

En este caso, se puede instalar el módulo PadWalker y hacer algo como esto (aquí está una versión modificada de su código originalmente publicado):

El guión main.pl:

my $a = 1; 

sub call_me { 
    print "unmodified: $a"; 
} 

use MOD; 

call_me; 

Y entonces su módulo :

package MOD; 

# closed_over($code_ref) returns a hash ref keyed on variable 
# name(including sigil) with values as references to the value 
# of those variables 
use PadWalker qw(closed_over); 

{ 
    # grab a reference to the original sub 
    my $orig = \&main::call_me; 

    # no need to use the symbol table, a glob reference is fine 
    # but you can't use sub main::call_me { ... } either 
    *main::call_me = sub { 
     my $a = closed_over($orig)->{'$a'}; 
     print "\$main::a = $$a\n"; 
    } 
} 
+0

funciona como un encanto! muchas gracias – user1247066

Cuestiones relacionadas