zoukankan      html  css  js  c++  java
  • Perl输出复杂数据结构:Data::Dumper,Data::Dump,Data::Printer

    输出复杂结构

    Data::DumperData::DumpData::Printer都可以用来输出复杂的数据结构。本文只介绍简单的几个输出形式,以后再需要的地方再详细介绍。

    前两者建议传递数据结构的引用给对应的函数、方法,当然直接传递非引用也不会错(标量、数组、哈希或引用都允许)。第三个Printer,则可以自动判断是否是引用。

    例如,下面的数据结构,一个是复杂的hash,一个是相对简单的匿名数组引用,分别使用这3个模块来输出。

    %Config = (
               'auto_commit' => '0',
               'build_dir' => '/home/fairy/.cpan/build',
               'bzip2' => '/bin/bzip2',
               'urllist' => [
                              'http://cpan.metacpan.org/',
                              @my_urllist     # 将数组my_urllist作为元素
                            ],
               'wget' => '/usr/bin/wget',
              );
    
    @my_urllist=('http://mirrors.aliyun.com/CPAN/',
                 'https://mirrors.tuna.tsinghua.edu.cn/CPAN/',
                 'https://mirrors.163.com/cpan/',
                 @more_urllist       # 将数组more_urllist引用作为元素
                );
    
    @more_urllist=qw(http://mirrors.shu.edu.cn/CPAN/
                     http://mirror.lzu.edu.cn/CPAN/
                    );
    
    $ref_arr=[qw(longshuai wugui fairy xiaofang)];
    

    1.使用Data::Dumper的Dumper函数,期待的是引用

    #!/usr/bin/perl
    use Data::Dumper;
    
    print Dumper(\%Config,$abc);
    

    输出结果:

    $VAR1 = {
              'wget' => '/usr/bin/wget',
              'urllist' => [
                             'http://cpan.metacpan.org/',
                             [
                               'http://mirrors.aliyun.com/CPAN/',
                               'https://mirrors.tuna.tsinghua.edu.cn/CPAN/',
                               'https://mirrors.163.com/cpan/',
                               [
                                 'http://mirrors.shu.edu.cn/CPAN/',
                                 'http://mirror.lzu.edu.cn/CPAN/'
                               ]
                             ]
                           ],
              'bzip2' => '/bin/bzip2',
              'auto_commit' => '0',
              'build_dir' => '/home/fairy/.cpan/build'
            };
    
    $VAR2 = [
              'longshuai',
              'wugui',
              'fairy',
              'xiaofang'
            ];
    

    注意,Dumper()将第一个引用赋值给$VAR1,第二个引用赋值给$VAR2。例如:

    如果想要将默认的$VAR修改为自定义的变量名称,可以使用Data::Dumper->Dump方法。

    2.使用Data::Dumper的Dump方法,期待两个数组引用,第二个数组引用用来定义现实的变量名,而不是默认的VAR

    #!/usr/bin/perl
    use Data::Dumper;
    
    print Data::Dumper->Dump([\%Config,$ref_arr],[qw(myvar myarr)]);
    

    以下是输出结果:

    $myvar = {
               'wget' => '/usr/bin/wget',
               'auto_commit' => '0',
               'bzip2' => '/bin/bzip2',
               'build_dir' => '/home/fairy/.cpan/build',
               'urllist' => [
                              'http://cpan.metacpan.org/',
                              [
                                'http://mirrors.aliyun.com/CPAN/',
                                'https://mirrors.tuna.tsinghua.edu.cn/CPAN/',
                                'https://mirrors.163.com/cpan/',
                                [
                                  'http://mirrors.shu.edu.cn/CPAN/',
                                  'http://mirror.lzu.edu.cn/CPAN/'
                                ]
                              ]
                            ]
             };
    $myarr = [
               'longshuai',
               'wugui',
               'fairy',
               'xiaofang'
             ];
    

    注意上面用了两个数组引用,第一个数组引用是待输出的复杂数据结构,第二个数组引用是定义前一个数组引用的变量名称。

    例如,下面的Dump方法,myvar定义\%Config的输出变量名称,myarr定义@name1的输出变量名称,@name2没有对应的变量名称,所以使用默认的$VAR3来输出。

    print Data::Dumper->Dump([\%Config,@name1,@name2],[qw(myvar,myarr)]);
    

    3.使用Data::Dump的dump方法,它输出时不会将输出结果赋值给标量变量,而是直接输出数据结构,有什么就输出什么

    例如,输出数组引用:

    #!/usr/bin/perl
    use Data::Dump qw(dump);
    
    print dump($ref_arr);
    

    输出结果:

    ["longshuai", "wugui", "fairy", "xiaofang"]
    

    输出hash引用:print dump(\%Config);

    {
      auto_commit => 0,
      build_dir => "/home/fairy/.cpan/build",
      bzip2 => "/bin/bzip2",
      urllist => [
        "http://cpan.metacpan.org/",
        [
          "http://mirrors.aliyun.com/CPAN/",
          "https://mirrors.tuna.tsinghua.edu.cn/CPAN/",
          "https://mirrors.163.com/cpan/",
          [
            "http://mirrors.shu.edu.cn/CPAN/",
            "http://mirror.lzu.edu.cn/CPAN/",
          ],
        ],
      ],
      wget => "/usr/bin/wget",
    }
    

    输出hash引用和匿名数组结果:print dump(\%Config,$ref_arr);

    (
      {
        auto_commit => 0,
        build_dir => "/home/fairy/.cpan/build",
        bzip2 => "/bin/bzip2",
        urllist => [
          "http://cpan.metacpan.org/",
          [
            "http://mirrors.aliyun.com/CPAN/",
            "https://mirrors.tuna.tsinghua.edu.cn/CPAN/",
            "https://mirrors.163.com/cpan/",
            [
              "http://mirrors.shu.edu.cn/CPAN/",
              "http://mirror.lzu.edu.cn/CPAN/",
            ],
          ],
        ],
        wget => "/usr/bin/wget",
      },
      ["longshuai", "wugui", "fairy", "xiaofang"],
    )
    

    4.使用Data::Printerp函数,它会直接输出结果,无需额外的print或say

    • p函数可以直接传递数据对象
    • 如果传递的是引用,则必须是引用变量,而不能是反斜线开头的引用
    • p函数不能同时格式化输出两个对象

    例如:

    p(%Config)      # 正确
    p($ref_Config)  # 正确
    p(\%Config)     # 错误
    p($ref_arr,$ref_Config)  # 错误
    

    首先安装这个模块:

    shell> cpan -i Data::Printer
    

    直接传递数据对象:

    use Data::Printer;
    
    p(%Config)
    

    以下是输出:

    {
        auto_commit   0,
        build_dir     "/home/fairy/.cpan/build",
        bzip2         "/bin/bzip2",
        urllist       [
            [0] "http://cpan.metacpan.org/",
            [1] [
                [0] "http://mirrors.aliyun.com/CPAN/",
                [1] "https://mirrors.tuna.tsinghua.edu.cn/CPAN/",
                [2] "https://mirrors.163.com/cpan/",
                [3] [
                    [0] "http://mirrors.shu.edu.cn/CPAN/",
                    [1] "http://mirror.lzu.edu.cn/CPAN/"
                ]
            ]
        ],
        wget          "/usr/bin/wget"
    }
    

    传递引用变量:

    p($ref_arr);
    

    以下是结果:

     [
        [0] "longshuai",
        [1] "wugui",
        [2] "fairy",
        [3] "xiaofang"
    ]
    

    让Dumper和eval结合

    由于Data::Dumper以及Data::Dump的输出中会包含变量,所以如果将dump出的结果持久化保存到文本后,可以在读取时使用eval将其直接构建成新的数据结构。

    例如:

    print DATA Dumper(\%Config);
    

    它将%Config的内容持久化到文件句柄DATA连接的文件中。当需要时,读取它并解除引用:

    open DATA, "<$datafile" or die "$!";
    {
        local $/;
        %new_Config = %{ eval <DATA> };
    }
    

    上面的eval使得perl去编译读取到的DATA,因为DATA是由Dumper出去的数据,它们都是变量开头的,所以eval <DATA>编译读取的内容后先进行赋值,然后返回赋值完成的类似$VAR1变量,由于这个标量变量是在解除引用的结构中,所以将新构建一个hash对象。

    但是上面的语句还有点问题,因为有时候持久化的文件可能会是空的,这时就会报错eval那里就会报错。为了健壮性,不得不加入更多的逻辑判断。

    比如,下面先将DATA的内容当作字符串赋值给变量变量$dumped_hash,然后判断这个变量。

    open DATA, "<$datafile" or die "$!"; 
    my $dumped_hash;
    {
        local $/;
        $dumped_hash = <DATA>;
    }
    my %new_Config = %{ eval $dumped_hash } if $dumped_hash;
    

    但是,以下是我见过最亮瞎狗眼的写法:

    %new_Config = %{ +eval { <DATA> } };
    

    用eval进行错误捕获,如果DATA不为空,则返回赋值后的变量$VAR1,前面加一个+得到+$VAR1,这个加号显式提示perl这是一个匿名hash,而不是一次性的语句块结构。然后解除引用。

  • 相关阅读:
    python-opencv-绘图函数
    sublime下package control安装无效解决
    关于vue.js中slot的理解
    关于vue.js父子组件数据传递
    oAuth2.0及jwt介绍
    nodejs文件上传组件multer使用
    nodejs设置服务端允许跨域
    添加swagger api文档到node服务
    关于for循环里面异步操作的问题
    nodejs记录2——一行代码实现文件下载
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/9719282.html
Copyright © 2011-2022 走看看