在perl4中,hash表中的value字段只能是scalar,而不能是list,这对于有些状况是很不方便的,好比有下面的数据: linux
Chicago, USA
Frankfurt, Germany
Berlin, Germany
Washington, USA
Helsinki, Finland
New York, USA 数组
咱们想要按国家将城市分类,每一个国家后面对应城市列表,若是用perl4来作,必须将城市列表组合成字符串才行,若是用perl5就能够用引用来作,有了引用,就能够构造复杂的hash结构,就能够用列表做为hash的值了。 数据结构
一、定义变量的时候,在变量名前面加个\,就获得了这个变量的一个引用,好比 app
# 数组的引用 my@array= (1,2,3) ; my$aref=\@array ; #哈希的引用 my%hash= ("name"=>"zdd","age"=>30,"gender"=>"male") ; my$href=\%hash ; #标量的引用 my$scalar=1 ; my$sref=\$scalar二、匿名引用
方法一不是很经常使用,最经常使用的仍是匿名引用,方法以下 函数
匿名数组引用-用[]定义 ui
$aref= [ 1,"foo",undef,13 ];匿名数组的元素仍然能够是匿名数组,因此咱们能够用这种方法构造数组的数组,能够构造任意维度的数组。
my $aref = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ]匿名哈希引用-用{}定义
$href= { APR =>4, AUG =>8 };
定义了引用以后,可使用不一样的方法来访问引用,这里主要有三种方法。记忆这三种方法有个诀窍,将他们与普通的变量访问做比较便可。 spa
一、与普通变量的访问方法相比,假设原来的变量名是name,则此方法在全部name出现的地方用$name代替,以下 scala
my $scalar = 1 ; my @array = (1, 2, 3) ; my %hash = ('zdd' => 30, 'autumn' => 27) ; my $sref = \$scalar ; # scalar reference my $aref = \@array ; # array reference my $href = \%hash ; # hash reference # 方法一 print $$sref, "\n" ; # 用$sref代替sref print @$aref, "\n" ; # 用$aref代替aref print %$href, "\n" ; # 用$href代替href print $$aref[2], "\n" ; print $$href{'zdd'}, "\n" ;二、 与普通变量的访问方法相比,假设变量原来的名字是name,则如今用{$name}来代替name。
@a @{$aref} An array reverse@a reverse @{$aref} Reverse the array $a[3] ${$aref}[3] An element of the array $a[3] =17; ${$aref}[3] =17 Assigning an element同理,哈希引用的使用方法以下。
%h %{$href} A hash keys%h keys%{$href} Get the keys from the hash $h{'red'} ${$href}{'red'} An element of the hash $h{'red'} =17 ${$href}{'red'} =17 Assigning an element
注意:当{}内部是$var的形式时,{}是能够省略的,也就是说@{$aref}等价于@$aref,不过初学最好养成使用{}的习惯。
code
$aref->[] #数组解引用 $href->{} #哈希解引用 $href->() #子过程解引用
$aref->[0] =3 ; $href->{name} ="autumn" ; $sref=2 ;
my $scalar = 1 ; my @array = (1, 2, 3) ; my %hash = ('zdd' => 30, 'autumn' => 27) ; my $sref = \$scalar ; # scalar reference my $aref = \@array ; # array reference my $href = \%hash ; # hash reference # 方法一 print $$sref, "\n" ; print @$aref, "\n" ; print %$href, "\n" ; print $$aref[2], "\n" ; print $$href{'zdd'}, "\n" ; # 方法二 print ${$sref}, "\n" ; print @{$aref}, "\n" ; print %{$href}, "\n" ; print ${$aref}[2], "\n" ; print ${$href}{'zdd'}, "\n" ; # 方法三,不适用于标量 print $aref->[0], "\n" ; print $href->{'zdd'}, "\n" ;
@a = ( [1, 2, 3], [4, 5, 6], [7, 8, 9] )
咱们知道[1, 2, 3]定义了一个(1, 2, 3)的匿名引用,因此数组a实际上包含三个元素,每一个元素是一个引用,该引用指向一个数组,因此咱们能够用下面的方法来访问数组元素(注意,下标从0开始) orm
$a[1][2]表示第二行第三列元素6,也能够写成$a[1]->[2],不过不多有人这么写。还能够写成${$a[1]}[2],几乎没人这么写!
my $aref = [1, [2, 3], [4, 5, 6]] ; print $aref->[0] , "\n" ; #1 print $aref->[1][1], "\n" ; #3 print $aref->[2][0], "\n" ; #4
也就是哈希表中的每一个元素也是一个哈希表,好比一个学生集合组成的哈希,其key是学生名字(惟一),其值是每一个学生的属性,好比年龄,身高及学号等。
my $student_properties_of = {
'zdd' => {
'age' => 30,
'hight' => 170,
'id' => '001',
},
'autumn' => {
'age' => 27,
'hight' => 165,
'id' => '002',
}
} ;赋值
$aref2 = $aref1; 将使得$aref2和$aref1指向同一个数组,若是想将$aref1指向的数组拷贝一份给$aref2的话,使用下面的方法,[]里面对数组进行解引用,而[]以解引用后的数组为内容生成了一个新的匿名数组,又赋值给$aref2。
$aref2 = [@{$aref1}];注意:不能使用下面的形式,外层的[]是不可缺乏的。因为=左边是标量,因此右边的数组会被解释为标量环境,获得的是数组元素个数,而不是元素自己。可是若是加上[]就能够了,这样perl知道这是一个匿名数组的赋值。
$aref2 = @{$aref1};
使用ref函数便可,若是变量是引用则返回真,不然返回假。实际上它更智能,它会返回引用对应的类型,好比HASH或者ARRAY。
my $aref1 = [1, 2, 0] ; print ref $aref1, "\n" ; #输出 ARRAY if (ref $aref1) { print "true\n" ; #输出 true }判断两个引用是否指向同一个目标
能够用eq,这将以字符串的形式判断,也可使用==
my $aref1 = [1, 2, 0] ; my $aref2 = $aref1 ; print $aref1, "\n" ; print $aref2, "\n" ; if ($aref1 eq $aref2) { print "reference equal\n" ; } if($aref1 == $aref2) { print "reference equal\n" ; }
stringified perl data structures, suitable for both printing and eval
perl因为有了引用,使得咱们能够在不一样的数据结构之间灵活的嵌套数据结构。比方说,Hash的value能够是标量,也能够嵌套list,甚至还能够继续嵌套hash。
# simple procedural interface print Dumper($foo, $bar);
# extended usage with names print Data::Dumper->Dump([$foo, $bar], [qw(foo *ary)]);
Data::Dumper有面向对象和直接使用函数两种调用方法,
use Data::Dumper; my @fruit = qw(apple banana orang); my @vegetable = ("tomato","potato","cabbage",\@fruit); my @meat = ("chicken","fish","beaf",\@vegetable); my $ref = \@meat; print "ref:@$ref","\n"; print "meat:@meat","\n"; print Dumper($ref); print Dumper(@meat);结果:
[mtk07256@mbjswgbm502 keyword_scan2]$perl testre.pl
ref:chicken fish beaf ARRAY(0xf211d8)
meat:chicken fish beaf ARRAY(0xf211d8)
$VAR1 = [
'chicken',
'fish',
'beaf',
[
'tomato',
'potato',
'cabbage',
[
'apple',
'banana',
'orang'
]
]
];
$VAR1 = 'chicken';
$VAR2 = 'fish';
$VAR3 = 'beaf';
$VAR4 = [
'tomato',
'potato',
'cabbage',
[
'apple',
'banana',
'orang'
]
];
Data::Dumper 和 Storage
结合Data::Dumper和Storable存储和从新获取数据。你能够用U盘将数据拷走
#!/usr/bin/perl -w use Data::Dumper; use Storable; my $a = "good"; my @myarray = ("hello", "world", "123", 4.5); my %myhash = ( "foo" => 35, "bar" => 12.4, "2.5"=> "hello", "wilma" => 1.72e30, "betty" => "bye/n"); print Dumper($a) ."\n"x2; print Dumper(\@myarray) ."\n"x2; print Dumper(\%myhash) ."\n"x2; print Dumper((\%myhash, \@myarray)) ."\n"x2;
#!/usr/bin/perl -w use Data::Dumper; use Storable; my $a = "good"; my @myarray = ("hello", "world", "123", 4.5); my %myhash = ( "foo" => 35, "bar" => 12.4, "2.5"=> "hello", "wilma" => 1.72e30, "betty" => "bye/n"); print Dumper($a) ."\n"x2; print Dumper(\@myarray) ."\n"x2; print Dumper(\%myhash) ."\n"x2; print Dumper((\%myhash, \@myarray)) ."\n"x2; ###use Storable print "\nmethod 1,use Storable retrieve data:\n"; store \%myhash,'./file.txt'; #保存数据 my $hashref=retrieve('./file.txt'); #从新获取数据 print Dumper(\%$hashref);
因为在linux系统执行store所生成的文件,在Windows下可能没法识别,而Dumper生成的文本文件能够跨系统恢复。
若是你想保存你的数据结构以便之后用于其余程序,那么你有不少方法能够用。最简单的方法就是使用 Perl 的 Data::Dumper 模块,它把一个(多是自参考的)数据结构变成一个字串,你能够把这个字串 保存在程序外部,之后用 eval 或者 do 从新组成:
use Data::Dumper; my %hash=('a'=>1,'b'=>2); open (FILE, "> hash_dumper") or die "can't open tvinfo: $!"; print FILE D; close FILE or die "can't close tvinfo: $!";
其余的程序(或者同一个程序)能够稍后从文件里把它读回来:
打印dumper的内容相比storable是可读的,并可用如下方法恢复成变量,
在使用 use strict 时失败。
open (FILE, "< hash_file") or die "can't open hash_file: $!"; local $/=undef; # 一次把整个文件读取进来 my $file=<FILE>; my $hashref= eval $file; # 从新生成##eval{$file}; 是无效的#### die "can't recreate tv data from tvinfo.perldata: $@" if $@; close FILE or die "can't close tvinfo: $!"; print %$hashref;
还有许多其余的解决方法能够用,它们的存储格式的范围从打包的二进制(很是快)到 XML( 互换性很是好)。检查一下靠近你的 CPAN 镜象!