Perl經常使用模塊 (Data::Dumper)

爲何使用引用?

在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
  • 前者是真正的數組,因此定義變量是使用@,後者是指向匿名數組的引用,因此定義的時候使用$
  • 前者的數組元素是匿名數組,而外層數組則是實體數組,後者不管元素仍是外層數組都是匿名數組
  • 前者能夠用$a[x][y]的形式訪問,然後者只能用解引用的方式訪問,即$a->[x][y]的形式。

哈希的哈希

也就是哈希表中的每一個元素也是一個哈希表,好比一個學生集合組成的哈希,其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" ;
}

Data::Dumper

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

相關文章
相關標籤/搜索