2012-07-13 12 views
5

Abbiamo al lavoro uno script Perl che viene utilizzato per eseguire la manutenzione. Avevo bisogno di modificarlo per gestire più attività. Il problema è che lo script è compilato e la fonte è stata persa molto tempo fa.Perl: accesso alle variabili "my" da un altro file

Ho cercato di usare B :: Deparse al fine di ricreare il file, ma Deparse non è perfetto e l'uscita è rotto (e molto grande ~ 5000 linee di codice deparsed).

Dopo aver letto il codice deparsato ho scoperto che ho bisogno di modificare una funzione. Lo script compilato carica un modulo di script in solo testo, quindi ho modificato il modulo per sovrascrivere la funzione ed eseguire l'attività che mi serve per eseguire. Il problema ora è che non posso accedere alle variabili "mie" dello script principale.

Ecco un esempio:

# 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"; 
} 

Il risultato è: "$main::a =" invece di ottenere il valore reale.

Grazie in anticipo.

+0

Le variabili lessicali ('my') non si visualizzano nella tabella dei simboli del pacchetto in contrasto con le globali dei pacchetti. Quindi questo è difficile, ma interessante ... # Sidenote: puoi semplicemente scrivere sub main :: call_me {...} se ricordo male. – amon

+0

Cosa intendi con "script compilato". Vuoi dire confezionato? – ikegami

+0

Sono d'accordo con ikegami, potrebbe esserci un modo per recuperare quello script, ma per sapere, dobbiamo sapere cosa intendi con "compilato". –

risposta

8

La risposta breve è che le variabili dichiarate con my non sono accessibili al di fuori del loro ambito lessicale. Se non puoi cambiare la dichiarazione a "nostra" (a causa della pazza natura "compilata" della sceneggiatura originale), non sei ancora sfortunato. Perl fornisce quasi sempre un modo per aggirare questo tipo di cose.

In questo caso, è possibile installare il modulo PadWalker e fare qualcosa di simile (qui una versione ottimizzato del codice originariamente scritto):

Il main.pl script:

my $a = 1; 

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

use MOD; 

call_me; 

E poi il modulo :

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

funziona come un fascino! molte grazie – user1247066

Problemi correlati