编写持久的perl脚本

Sma*_*elf 4 unix linux bash perl

我正在尝试编写持久/缓存脚本.代码看起来像这样:

...
Memoize('process_fille');
print process_file($ARGV[0]);
...
sub process_file{
    my $filename = shift;
    my ($a, $b, $c) = extract_values_from_file($filename);
    if (exists $my_hash{$a}{$b}{$c}){
        return $my_hash{$a}{$b}{$c};
    }
    return $default;
}
Run Code Online (Sandbox Code Playgroud)

这将从循环中的shell脚本调用,如下所示

value=`perl my_script.pl`;
Run Code Online (Sandbox Code Playgroud)

有没有办法可以调用这个脚本,以保持其状态.从打电话到打电话.让我们假设初始化'%my_hash'和调用extract_values_from_file都是一项昂贵的操作.

谢谢

mob*_*mob 10

这是一种黑魔法,但你可以在脚本的__DATA__令牌之后存储状态并保持它.

use Data::Dumper; # or JSON, YAML, or any other data serializer
package MyPackage;
my $DATA_ptr;
our $state;
INIT {
    $DATA_ptr = tell DATA;
    $state = eval join "", <DATA>;
}

...
manipulate $MyPackage::state in this and other scripts
...

END {
    open DATA, '+<', $0;   # $0 is the name of this script
    seek DATA, $DATA_ptr, 0;
    print DATA Data::Dumper::Dumper($state);
    truncate DATA, tell DATA;  # in case new data is shorter than old data
    close DATA;
}
__DATA__
$VAR1 = {
    'foo' => 123,
    'bar' => 42,
    ...
}
Run Code Online (Sandbox Code Playgroud)

INIT块中,存储文件__DATA__部分开头的位置并反序列化您的状态.在END块中,您重新序列化当前状态并覆盖__DATA__脚本部分.当然,运行脚本的用户需要具有脚本的写权限.

编辑使用INIT块而不是BEGIN块 - DATA在编译阶段不设置块.

  • 序列化状态 - 是的.在自己里面重写它 - 真该死!这可能看起来很时髦,产生+1或2,但维护完全一团糟. (5认同)
  • 非常酷,但打印到您的实际源代码文件似乎不健康. (3认同)

Ole*_*kov 6

如果示例中的%my_hash在其最终初始化状态下具有中等大小,则可以使用序列化模块之一(如Storable,JSON :: XSData :: Dumper)在运行之间以预先组装的形式保存数据.缺席时生成新文件,并在存在时重新加载就绪内容.

另外,您已经提到过要在循环中调用此脚本.一个好的策略是不要在循环内立即调用脚本,而是构建一个参数队列,然后在单次执行循环之后将它们全部传递给脚本.脚本将设置其环境,然后循环遍历参数,轻松完成工作,而无需为每个参数重做设置步骤.