2012-07-13 6 views
5

Mamy w pracy skrypt Perla, który jest używany do wykonywania konserwacji. Musiałem go zmodyfikować, aby obsługiwał więcej zadań. Problem polega na tym, że skrypt został skompilowany, a źródło utracono dawno temu.Perl: Dostęp do "moich" zmiennych z innego pliku

Próbowałem użyć B :: Deparse w celu odtworzenia pliku, ale Deparse nie jest doskonały, a wynik jest zepsuty (i bardzo duży ~ 5000 linii deparsed code).

Po przeczytaniu deparowanego kodu stwierdziłem, że muszę zmodyfikować jedną funkcję. Skompilowany skrypt ładuje moduł skryptu tekstowego, więc zmieniłem moduł, aby nadpisać funkcję i wykonać zadanie, którego potrzebuję do wykonania. Problem polega na tym, że nie mogę uzyskać dostępu do skryptu głównego "moje" zmienne.

Oto przykład:

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

Wynikiem jest: "$main::a =" zamiast się realnej wartości.

Z góry dziękuję.

+0

Zmienne leksykalne ("my") nie pojawiają się w tabeli symboli pakietu w przeciwieństwie do globali pakietu. To jest trudne, ale interesujące ... # Sidenote: możesz po prostu napisać sub główne :: call_me {...}, jeśli dobrze pamiętam. – amon

+0

Co masz na myśli przez "skompilowany skrypt". Masz na myśli pakowane? – ikegami

+0

Zgadzam się z ikegami, może być jakiś sposób na odzyskanie tego skryptu, ale żeby wiedzieć, musimy wiedzieć, co masz na myśli przez "skompilowany". –

Odpowiedz

8

Krótka odpowiedź brzmi, że zmienne zadeklarowane jako my nie są dostępne poza ich zakresem leksykalnym. Jeśli nie możesz zmienić deklaracji na "nasz" (z powodu zwariowanej "skompilowanej" natury oryginalnego skryptu), nie masz jeszcze szczęścia. Perl prawie zawsze zapewnia sposób obejścia tego typu rzeczy.

W tym przypadku można zainstalować moduł PadWalker i zrobić coś takiego (tu jest manipulowane wersję swojej Cytat kodzie):

main.pl scenariusz:

my $a = 1; 

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

use MOD; 

call_me; 

I wówczas moduł :

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

działa jak urok! wielkie dzięki – user1247066

Powiązane problemy