【问题标题】:How do I read back in the output of Data::Dumper?如何回读 Data::Dumper 的输出?
【发布时间】:2010-09-29 21:39:06
【问题描述】:

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

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

我想读回那个文件并找回$x。我试过这个:

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

eval $vars;

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

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

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

【问题讨论】:

  • Data::Dumper 并不是存储数据的好选择。它更像是一个调试工具。

标签: perl persistence data-dumper


【解决方案1】:

这对我来说很好用:

写出来:

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 $@;

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

      这个 sn-p 很短,对我有用(我正在阅读数组)。它从第一个脚本参数中获取文件名。

      
      # Load in the Dumper'ed library data structure and eval it
      my $dsname = $ARGV[0];
      my @lib = do "$dsname";
      

      【讨论】:

        【解决方案4】:

        如果您想保留一些简单易读的内容,只需使用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,看起来像(至少在我的电脑上):

        [{ 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

        【讨论】:

          【解决方案5】:

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

          • Storable - 这既快速又简单,但相当特定于 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);

          【讨论】:

          • 如果系统上安装了 JSON 模块,现在默认使用 JSON::XS
          【解决方案6】:

          我想你想放

          our $x;
          

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

          话虽如此,我与其他声音一起建议可存储。

          【讨论】:

            【解决方案7】:

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

            $Data::Dumper::Purity = 1;
            

            $obj->Purity(1);
            

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

            详情请见the Data::Dumper documenatation at CPAN

            【讨论】:

              【解决方案8】:

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

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

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

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

              这样就可以了:

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

              【讨论】:

                【解决方案9】:

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

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

                祝你好运,:)

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2010-12-08
                  • 2011-06-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-09-03
                  • 2017-02-09
                  • 1970-01-01
                  相关资源
                  最近更新 更多