Data::Dumper
、Data::Dump
、Data::Printer
均可以用来输出复杂的数据结构。本文只介绍简单的几个输出形式,之后再须要的地方再详细介绍。shell
前二者建议传递数据结构的引用给对应的函数、方法,固然直接传递非引用也不会错(标量、数组、哈希或引用都容许)。第三个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);
输出结果:ui
$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
。例如:url
若是想要将默认的$VAR
修改成自定义的变量名称,可使用Data::Dumper->Dump
方法。code
2.使用Data::Dumper
的Dump方法,期待两个数组引用,第二个数组引用用来定义现实的变量名,而不是默认的VAR对象
#!/usr/bin/perl use Data::Dumper; print Data::Dumper->Dump([\%Config,$ref_arr],[qw(myvar myarr)]);
如下是输出结果:ip
$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::Printer
的p
函数,它会直接输出结果,无需额外的print或say
例如:
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" ]
因为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,而不是一次性的语句块结构。而后解除引用。