from: http://www.cnblogs.com/polestar/archive/2012/05/03/2480118.html
子例程,函數
子例程,函數的作用域是指在程序中能夠看到它的位置範圍。子例程是全局的,可以放在腳本中的任意位置,甚至放在其他腳本文件中。當使用來自其他文件的子例程時,應當使用關鍵字do,require或use將它加載到腳本里。若要調用一個子例程,用戶可以在子例程前加上&符號,或在子例程前加上do關鍵字,也可以在子例程名後面加上一組括號。如果使用了向前引用(forward reference),在調用子例程時就不需要提供&或括號。
1 Subroutine declaration: 2 sub subroutine_name; 3 Subroutine definition: 4 sub subroutine_name{ Block } 5 Subroutine call: 6 do subroutine_name; 7 &subroutine_name; 8 subroutine_name(); 9 subroutine_name; 10 Subroutine call with parameters: 11 &subroutine_name( parameter1,parameter2,.......); 12 subroutine_name( parameter1,parameter2,.......);
示例代碼:
1 #!/user/bin/perl 2 3 sub greetme 4 { 5 print "Welcome,Valkommen till,Bienvenue!\n"; 6 } 7 8 &greetme if defined &greetme; #使用defined函數檢查子例程是否已經定義。在使用子例程名時,要求必須提供&標記。 9 10 print "Program continues ....\n"; 11 12 &greetme; 13 14 bye(); 15 &bye; 16 #bye; 此種方式調用需使用向前引用,類似C程序中的聲明。 17 sub bye; 18 bye; 19 20 sub bye 21 { 22 print "Bye,adjo,adieu.\n"; 23 } 24 25 bye(); 26 &bye; 27 bye;
運行結果:
1 Welcome,Valkommen till,Bienvenue! 2 Program continues .... 3 Welcome,Valkommen till,Bienvenue! 4 Bye,adjo,adieu. 5 Bye,adjo,adieu. 6 Bye,adjo,adieu. 7 Bye,adjo,adieu. 8 Bye,adjo,adieu. 9 Bye,adjo,adieu.
參數傳遞
函數把接收到的參數保存到特殊的perl數組@_中,其中每個元素($_[0],$_[1],.....)稱作一個參數。不論參數是標量型還是數組型的,用戶把參數傳給子例程時,perl默認按引用的方式調用它們。用戶可以通過改變@_數組中的值來改變相應實際參數的值。
示例代碼:
1 #!/usr/bin/perl 2 3 sub params 4 { 5 print 'The values in the @_array are ',"@_\n";#將打印整個數組 6 print "The first value is $_[0]\n"; 7 print "The last value is ",pop(@_),"\n";#最後一個參數被彈出@_數組,實際參數的個數並未改變 8 9 foreach $value (@_) 10 { 11 $value+=5; 12 print "The value is $value","\n"; 13 } 14 } 15 16 @n=(1,2,3,4,5); 17 params(@n); 18 print "Black in main\n"; 19 print "The new values are @n \n";
運行結果:
1 The values in the @_array are 1 2 3 4 5 2 The first value is 1 3 The last value is 5 4 The value is 6 5 The value is 7 6 The value is 8 7 The value is 9 8 Black in main 9 The new values are 6 7 8 9 5 #前四個參數值已經改變,最後一個參數值沒有發生變化,因爲子例程中執行了pop(@_).
local與my區別
任何使用local函數聲明的變量都是動態拷貝的。該變量不但在創建它的塊中可見,而且對於任何從該代碼塊調用的函數中也是可見的。與local函數聲明的變量不同,my函數聲明得到的所有變量都只在聲明它的子例程中可見,對於該子例程調用的任何其他子例程都是不可見的
內部->外部:
1)my和local都只在一個block裏有效,出去就失效;
2)但是local的變量可以繼續在這個block中調用的子程序中存在;
3)如果有與外界同名的變量,兩者在block退出後都不影響外界同名變量;
外部->內部:
如果在一個block中有一個my修飾的變量和外界的一個變量同名,而且又需要在這個block中使用外界變量時,兩個辦法:第一個辦法,用main的package修飾這個變量名,$main::global。第二個辦法,用our修飾,our $global,那麼該block中接下來出現的所有$global都是外界的global
示例代碼:
1 #!/usr/bin/perl 2 $x = 9; 3 sub mm{ 4 print "$x\n"; 5 } 6 sub gg_my{ 7 my $x = 11; 8 print "call-my $x\n"; 9 our $x; 10 print "our-global $x\n"; 11 mm; 12 } 13 sub gg_local { 14 local $x = 20; 15 print "call-local $x\n"; 16 mm; 17 } 18 gg_my; 19 gg_local; 20 print $x;
運行結果:
1 call-my 11 2 our-global 9 3 9 4 call-local 20 5 20 6 9
創建指針和訪問指針地址
賦值 | 創建引用 | 訪問地址 | 使用箭頭運算符訪問地址 |
$sca = 5 | $p=\$sca | print $$p | |
@arr=(4,5,6) | $p=\@arr | print @$p | $p->[0] |
print $$p[0] | |||
%hash=(key=>'value') | $p=\%hash | print %$p | $p->{key} |
print $$p{key} |
指針參數
當一個子例程接收參數時,便會把參數保存到@_數組中。當把兩個數組同時傳遞給一個子例程時,這兩個數組都將保存到@_數組中,並連接成單個列表。如果不知道其中前一個數組長度的話,基本上就不可能再拆開這兩個數組了。不過,如果傳遞給子例程的是兩個指針,分別含有這兩個數組地址的話,就可以方便地實現數組內容的分離。
示例代碼:
1 #!/usr/bin/perl 2 3 my @list1=(1..100); 4 my @list2=(5,10,15,20); 5 6 print "the total is :" ,&addemup(\@list1,\@list2),".\n"; 7 8 sub addemup 9 { 10 my( $arr1,$arr2) =( shift,shift);# The two pointers are shifted from @_ 11 12 my $total=0; 13 print $arr1,"\n"; 14 print $arr2,"\n"; 15 16 foreach $num(@$arr1,@$arr2) 17 { 18 $total+=$num; 19 } 20 $total; #相當於 return $total; 21 }
執行結果:
1 ARRAY(0x182a944) 2 ARRAY(0x183728c) 3 the total is :5100.
文件句柄的引用
示例代碼:
1 #!/usr/bin/perl 2 3 open( README,"D:\\perlwork1\\perl.pl") || die; 4 5 &readit(\*README);#reference to a typeglob 6 7 sub readit 8 { 9 my ($passwd)=@_; 10 print "\$passwd is a $passwd.\n"; 11 while(<$passwd>) 12 { 13 print; 14 } 15 }
執行結果:
1 $passwd is a GLOB(0x182a964). 2 #!usr/bin/perl 3 。。。。