我使用Data :: Dumper在Perl中序列化了我的数据.现在,当我评估它时,我得到"全局符号"$ VAR1"需要显式包名"

bod*_*ydo 3 perl serialization eval data-dumper

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

Global symbol "$VAR1" requires explicit package name
Run Code Online (Sandbox Code Playgroud)

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

以下是我eval的代码:

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

如何禁止我的程序死亡,因为"$VAR1"没有被声明为my

我应该追加"my "$db_row->{categories}eval?像这样:

my $wiki_categories = eval("my ".$db_row->{categories});
Run Code Online (Sandbox Code Playgroud)

我还没有测试过,但我认为它会起作用.

还有其他方法吗?也许将它包装在某个块中,然后对该块关闭严格?我从来没有这样做,但我已经看到它提到了.

任何帮助赞赏!

Sch*_*ern 8

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

$VAR1 = ...your data...
Run Code Online (Sandbox Code Playgroud)

要使用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;
Run Code Online (Sandbox Code Playgroud)

然后结果可以直接变成变量.

my $data = eval $your_dump;
Run Code Online (Sandbox Code Playgroud)

你可以做各种技巧来缩小Data :: Dumper的大小,但总的来说它快速且节省空间.主要的缺点是它只是Perl并且非常不安全.如果任何人都可以修改您的转储文件,他们拥有您的程序.

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


Tan*_*lus 6

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

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

下一个含义是你绑定到Data :: Dumper.同样,数据可能已经存在,所以太糟糕了,使用它.如果不是这种情况,我建议切换到另一种可存储的格式.现在相当常见的是JSON.虽然JSON不是核心perl的一部分,但安装起来非常简单.它也使这更容易.一个优点是数据也可用于其他语言.另一个原因是你避免使用eval STRING,如果数据受到损害,可能很容易损害你的消费者.

下一个项目就是如何解决它.例如,如果数据存在.一个简单的解决方案就是像你一样添加我的.这很好用.另一个是剥离$ VAR1 : (my $dumped = $db_row->{categories}) =~ s/^\s*\$\w+\s*=\s*//;. 另一个是将"无警告"放入评估中:eval ("no warnings; no strict; " . $db_row->{categories});.

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