将Perl中的匿名sub写入文件以供以后使用

将Perl中的匿名sub写入文件以供以后使用,perl,hash,functional-programming,generative-programming,Perl,Hash,Functional Programming,Generative Programming,我有一个Perl程序,它从输入文件中生成解析规则作为sub。这些sub是匿名定义的,并放入一个散列中。现在,我想导出该散列,以及所有的sub,然后稍后再次加载它们以用于不同的程序 我该怎么做呢?是否有某种方法可以提取每个sub的代码,或者我可以复制散列所在的内存块,然后在稍后再次加载时将其转换为散列 提前感谢。可以处理存储其他Perl类型之外的代码引用。各种模块,甚至Data::Dumper也是如此。来自可存储文档的一节(特别强调): 自可存储版本2.05以来,可以借助B::Deparse对代码

我有一个Perl程序,它从输入文件中生成解析规则作为sub。这些sub是匿名定义的,并放入一个散列中。现在,我想导出该散列,以及所有的sub,然后稍后再次加载它们以用于不同的程序

我该怎么做呢?是否有某种方法可以提取每个sub的代码,或者我可以复制散列所在的内存块,然后在稍后再次加载时将其转换为散列

提前感谢。

可以处理存储其他Perl类型之外的代码引用。各种模块,甚至Data::Dumper也是如此。

来自可存储文档的一节(特别强调):

自可存储版本2.05以来,可以借助B::Deparse对代码引用进行序列化。要启用此功能,请将
$Storable::Deparse
设置为真值。要启用反序列化,
$Storable::Eval
应设置为真值请注意,反序列化是通过
eval
完成的,如果可存储文件包含恶意数据,这将非常危险。

在下面的演示中,子进程创建匿名子进程的散列。然后父进程在一个完全独立的进程和地址空间中,因此它看不到
%dispatch
——从
冻结
读取输出,就像从磁盘上的文件读取一样

#! /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;
}
#/usr/bin/perl
使用警告;
严格使用;
使用可储存的qw/冻融/;
my$pid=打开my$fh,“-|”;
模具“$0:fork:$!”除非定义为$pid;
如果($pid==0){
#子进程
我的%dispatch=(
foo=>sub{print“Yo!\n”},
bar=>sub{print“Hi!\n”},
baz=>sub{print“Holla!\n”},
);
本地$Storable::Deparse=1 | |$Storable::Deparse;
binmode标准输出“:字节”;
打印冻结\%发送;
出口0;
}
否则{
#父进程
本地$/;
binmode$fh,“:字节”;
我的美元冻结=;
本地$Storable::Eval=1 | |$Storable::Eval;
my$d=解冻$freezed;
$d->{${}()键%$d;
}
输出:

Hi! Holla! Yo! 你好 你好!
哟!不用保存实际编译的sub,你可以保存sub的文本,然后在新的过程中将它们重新评估为coderef。是的,我想到了。但出于美观原因,我希望能够保存已编译的Sub:-据我所知,pAll技术使用B::Deparse将代码引用翻译回Perl源代码。此过程可能不会返回与开始时相同的源代码。我不认为这会比简单地保存实际的原始文本更划算。我可以简单地将
$freezed
写入文本文件吗?别担心,我会清理我的输入。我从XKCD学到了这一点:D@Mechko是的,在您的代码中,您需要将输出写入磁盘上的一个文件,然后再将其读入。我更改了演示,使其与管道两侧的外观相似。