2010-02-04 24 views
7

Ich habe ein Perl-Programm, das Parsing-Regeln als Subs aus einer Eingabedatei generiert. Die Subs werden anonym definiert und in einen Hash eingegeben. Nun möchte ich diesen Hash mit allen Subs exportieren und sie später wieder laden, um sie mit einem anderen Programm zu verwenden.Schreiben Sie eine anonyme Sub in Perl in eine Datei für die spätere Verwendung

Wie gehe ich dabei vor? Gibt es eine Möglichkeit, den Code jedes Subs zu extrahieren, oder kann ich den Speicherblock kopieren, in dem der Hash vorhanden ist, und ihn dann als Hashwert ausgeben, wenn ich ihn später erneut lade?

Vielen Dank im Voraus.

+0

Anstatt der tatsächlichen kompilierte subs retten, könnten Sie den * Text * der U-Boote speichern, und dann erneut eval sie in coderefs in dem neuen Prozess. – Ether

+0

Ja, ich habe daran gedacht. Aber ich möchte die kompilierten Subs aus ästhetischen Gründen speichern können. :-p –

+0

Alle Techniken, die ich kenne, verwenden B :: Deparse, um die Code-Referenz zurück in Perl-Quellcode zu übersetzen. Dieser Prozess gibt möglicherweise nicht denselben Quellcode zurück, mit dem Sie begonnen haben. Ich glaube nicht, dass Sie dadurch viel Geld sparen, indem Sie einfach den eigentlichen Originaltext speichern. –

Antwort

2

Vom "Code References" Abschnitt der speicherbaren Dokumentation (mit Hervorhebungen):

Seit Storable Version 2.05 können CODE Referenzen mit Hilfe von B::Deparse serialisiert werden. Um diese Funktion zu aktivieren, setzen Sie $Storable::Deparse auf einen wahren Wert. Um die Deserialisierung zu aktivieren, sollte $Storable::Eval auf einen wahren Wert gesetzt werden. Beachten Sie, dass die Deserialisierung über eval erfolgt, was gefährlich ist, wenn die speicherbare Datei schädliche Daten enthält.

In der folgenden Demo erstellt ein untergeordneter Prozess den Hash der anonymen Subs. Dann die Eltern-in einem völlig separaten Prozess-und Adressraum, so dass es nicht sehen %dispatch - liest die Ausgabe von freeze auf die gleiche Weise, wie Sie möglicherweise von einer Datei auf der Festplatte.

#! /usr/bin/perl 

use warnings; 
use strict; 

use Storable qw/ freeze thaw /; 

my $pid = open my $fh, "-|"; 
die "$0: fork: $!" unless defined $pid; 

if ($pid == 0) { 
    # child process 
    my %dispatch = (
    foo => sub { print "Yo!\n" }, 
    bar => sub { print "Hi!\n" }, 
    baz => sub { print "Holla!\n" }, 
); 

    local $Storable::Deparse = 1 || $Storable::Deparse; 
    binmode STDOUT, ":bytes"; 
    print freeze \%dispatch; 
    exit 0; 
} 
else { 
    # parent process 
    local $/; 
    binmode $fh, ":bytes"; 
    my $frozen = <$fh>; 

    local $Storable::Eval = 1 || $Storable::Eval; 
    my $d = thaw $frozen; 
    $d->{$_}() for keys %$d; 
} 

Ausgang:

Hi! 
Holla! 
Yo!
+0

und ich kann einfach '$ eingefroren' in eine Textdatei schreiben? und keine Sorge, ich werde meine Eingaben bereinigen. Ich habe dies von XKCD gelernt: D –

+0

@Mechko Ja, in Ihrem Code würden Sie die Ausgabe in eine Datei auf der Festplatte schreiben und dann später einlesen. Ich habe die Demo geändert, um zu sehen, wie beide Seiten Ihrer Pipeline aussehen könnten. –

Verwandte Themen