5

假设我有一个使用创建的文本文件Data::Dumper,大致如下:

my $x = [ { foo => 'bar', asdf => undef }, 0, -4, [ [] ] ];

我想读回那个文件然后$x回来。我试过这个:

my $vars;
{
  undef $/;
  $vars = <FILE>;
}

eval $vars;

但它似乎没有工作 -$x不仅没有定义,当我尝试使用它时,我收到一个警告

全局符号 $x 需要明确的包名。

这样做的正确方法是什么?(是的,我知道它很丑。它是一个快速实用的脚本,而不是生命支持系统。)

4

9 回答 9

11

这是一个提供几个不同选项的线程:Undumper

如果您只是在寻找数据持久性,那么 Storable 模块可能是您最好的选择。

于 2009-01-06T20:40:33.260 回答
10

正如其他人已经说过的那样,您最好以更好的序列化格式存储数据:

  • 可存储- 这既快速又简单,但相当特定于 Perl(但可以轻松满足您在相对不重要的脚本中快速解决方案的需求)
  • YAML,使用YAML模块或YAML::TinyYAML::Any作为包装器,以利用系统上可用的任何 JSON 模块
  • JSON,使用JSON模块或JSON::XS以提高速度(或JSON::Any作为包装器以利用系统上可用的任何 JSON 模块)
  • XML,使用XML-Simple模块或其他 XML 模块之一。

就个人而言,我认为我的目标是 YAML 或 JSON ......你不能比以下更容易:

my $data = YAML::Any::LoadFile($filename);

于 2009-01-06T23:03:14.640 回答
8

默认情况下,eval 无法解析 Data::Dumper 输出,尤其是当被转储的数据结构在某种程度上是循环的时。但是,您可以设置

$Data::Dumper::Purity = 1;

或者

$obj->Purity(1);

objData::Dumper 对象在哪里。这些中的任何一个都会导致 Data::Dumper 产生可以被 eval 解析的输出。

有关所有详细信息,请参阅CPAN 的 Data::Dumper 文档。

于 2009-01-06T21:56:47.943 回答
6

正如 Rich 所说,您可能不想使用 Data::Dumper 进行持久性,而是使用类似Storable的东西。

但是,要回答所提出的问题... IIRC,Data::Dumper 没有将您的变量声明为my,那么您是否以某种方式自己这样做?

为了能够eval将数据重新输入,变量不需要my在 eval 中。如果您的文本文件包含以下内容:

$x = [ { foo => 'bar', asdf => undef }, 0, -4, [ [] ] ];

那么这将起作用:

my $vars;
{
  undef $/;
  $vars = <FILE>;
}

my $x;    
eval $vars;
print $x;
于 2009-01-06T21:39:18.227 回答
3

如果你想保留一些简单易读的东西,只需使用Data::Dump模块而不是Data::Dumper. 基本上,它是Data::Dumper正确的——它产生了有效的 Perl 表达式,准备好赋值,而没有创建所有那些奇怪$VAR1$VAR2等变量。

然后,如果您的代码如下所示:

my $x = [ { foo => 'bar', asdf => undef }, 0, -4, [ [] ] ];

使用以下方法保存:

use Data::Dump "pp";
open F, ">dump.txt";
print F pp($x);

这会生成一个dump.txt看起来像(至少在我的 PC 上)的文件:

[{ asdf => undef, foo => "bar" }, 0, -4, [[]]]

加载它使用:

open F, "dump.txt";
my $vars;
{ local $/ = undef; $vars = <F>; }
my $x = eval $vars;

注意

  1. 如果您不想将赋值$/放在它自己的块中,您应该使用local以确保它的值实际上在块的末尾恢复;和
  2. 的结果eval()需要分配给$x.
于 2009-01-07T14:55:42.970 回答
1

这个片段很短并且对我有用(我正在阅读一个数组)。它从第一个脚本参数中获取文件名。


# Load in the Dumper'ed library data structure and eval it
my $dsname = $ARGV[0];
my @lib = do "$dsname";
于 2009-06-06T17:18:15.053 回答
1

您确定该文件是由 Data::Dumper 创建的吗?里面不应该my有。

其他一些选项是 Storable、YAML 或 DBM::Deep。我在Mastering Perl的“持久性”一章中浏览了一些示例。

祝你好运, :)

于 2009-01-06T21:40:23.933 回答
0

我想你想把

our $x;

在访问 x 之前进入您的代码。这将满足严格的错误检查。

话虽如此,我加入了其他声音的建议 Storable。

于 2009-01-06T22:00:07.187 回答
0

这对我来说很好:

写出:

open(my $C, qw{>}, $userdatafile) or croak "$userdatafile: $!";
use Data::Dumper;
print $C Data::Dumper->Dump([\%document], [qw(*document)]);
close($C) || croak "$userdatafile: $!";

读入:

open(my $C, qw{<}, $userdatafile) or croak "$userdatafile: $!";
local $/ = $/;
my $str = <$C>;
close($C) || croak "$userdatafile: $!";
eval { $str };
croak $@ if $@;
于 2009-01-06T22:13:55.503 回答