在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 鏡象!