3

我使用 Data::Dumper 将我的数据序列化为 Perl 中的字符串。现在在另一个程序中,我试图通过使用反序列化它,eval我得到:

Global symbol "$VAR1" requires explicit package name

use warnings; use strict;在我的程序中使用。

这是我eval编写代码的方式:

my $wiki_categories = eval($db_row->{categories});
die $@ if $@;
/* use $wiki_categories */

我怎样才能禁用我的程序因为"$VAR1"没有被声明为而死亡my

我应该在in"my "之前附加吗?像这样:$db_row->{categories}eval

my $wiki_categories = eval("my ".$db_row->{categories});

我还没有对此进行测试,但我认为它会起作用。

还有其他方法可以做到这一点吗?也许将它包装在某个块中,然后对该块关闭严格?我从来没有做过,但我看到它提到过。

任何帮助表示赞赏!

4

3 回答 3

8

这个是正常的。默认情况下,当 Data::Dumper 序列化数据时,它会输出如下内容:

$VAR1 = ...your data...

要使用 Data::Dumper 进行序列化,需要稍微配置一下。 Terse作为最重要的设置选项,它会关闭它$VAR

use Data::Dumper;

my $data = {
    foo => 23,
    bar => [qw(1 2 3)]
};

my $dumper = Data::Dumper->new([]);
$dumper->Terse(1);

$dumper->Values([$data]);
print $dumper->Dump;

然后可以将结果直接评估为变量。

my $data = eval $your_dump;

您可以使用各种技巧来缩小 Data::Dumper 的大小,但总体而言,它既快速又节省空间。主要的缺点是它只是 Perl 并且非常不安全。如果有人可以修改您的转储文件,他们就拥有您的程序。

CPAN 上有一些模块可以为您解决这个问题,还有更多模块,例如Data::Serializer

于 2012-06-21T19:13:30.727 回答
6

你的问题有很多含义,我会尽可能多地解决。

首先,阅读 Data::Dumper 的 perldoc。设置$Data::Dumper::Terse = 1可能足以满足您的需求。全局变量这里有很多选项,所以一定要本地化它们。但这会改变数据的生产者,而不是消费者。我不知道你有多少控制权。您的问题意味着您正在为消费者工作,但没有提及对生产者的任何控制。也许数据已经存在,您必须按原样使用它。

下一个含义是您与 Data::Dumper 相关联。同样,数据可能已经存在,所以太糟糕了,使用它。如果不是这种情况,我建议切换到另一种可存储格式。现在相当普遍的是 JSON。虽然 JSON 不是核心 perl 的一部分,但安装起来非常简单。它也使这变得容易得多。一个优点是这些数据在其他语言中也很有用。另一个是你避免 eval STRING,如果数据被泄露,很容易危及你的消费者。

下一项就是如何按原样解决它。例如,如果数据存在。一个简单的解决方案是像你一样添加 my 。这工作正常。另一种是剥离 $VAR1: (my $dumped = $db_row->{categories}) =~ s/^\s*\$\w+\s*=\s*//;。另一种是将“无警告”直接放入 eval:eval ("no warnings; no strict; " . $db_row->{categories});中。

就个人而言,我尽可能使用 JSON。

于 2012-06-21T19:15:57.407 回答
2

您的代码将按原样工作,除了eval失败,因为$VAR1在范围内未声明eval并且use strict 'vars'有效。

通过在尽可能紧的块内禁用限制来解决此问题。一个do块就可以了,就像这样

my $wiki_categories = do {
  no strict 'vars';
  eval $db_row->{categories};
};
于 2012-06-21T19:49:34.787 回答