符號表
每個包都有自己的一個符號表,它是一個雜湊表;關鍵字是包中的變數名、檔案控制代碼、目錄控制代碼以及子常式,值是typeglob
每個符號都被賦予一個typeglob(即*x),它表示所有名為x的類型。
每個包都有自己的符號表。無論何時使用包聲明,都要切換到該包的符號表。從一個包中訪問另外一個包的變數,可通過“ 包名 + 雙冒號( :: ) + 變數名 " 的方式指定。由於 my 函數賦值的變數不能從其所在的包外面訪問,而且它也沒有儲存在包符號表中,而是儲存在為每個子程式所建立的緩衝區裡。因此,在使用 "my" 變數時,使用者無法通過包的符號表來訪問它們,因為它們根本不在那裡!
require函數
require 可以匯入 Perl 庫,然後便可執行其中的常式或代碼,它類似於 C 語言中的 #include 。
使用 require 的格式為:require EXPR 。也可以不帶參數,此時該函數匯入的就是 $_ 變數值。require 匯入的庫檔案要存在於 @INC 所包含的某個路徑之中,否則函數將執行失敗,並返回類似於下面的資訊:
1 $ ./require.pl2 Can't locate hello.pl in @INC (@INC contains: /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .) at ./require.pl line 3.
測試代碼:
1 #!/usr/bin/perl2 require "pwd.pl";3 require "ctime.pl";4 &initpwd; #初始化函數,位於 pwd.pl 中5 printf "The present working directory is %s\n", $ENV{PWD};6 &chdir ("../.."); #切換目錄,該函數位於 pwd.pl 中7 printf "The present working directory is %s\n", $ENV{PWD};8 $today = &ctime(time); #擷取時間,該函數位於 ctime.pl 中9 print "$today";
執行結果:
1 $ ./require.pl2 The present working directory is /home/beyes/perl/package3 The present working directory is /home/beyes
如果開啟 pwd.pl 或 ctime.pl 這樣的庫檔案時,可能會注意到,庫檔案中的最後一行語句是 " 1; " 。對於 require 函數來說這是必須的,此時 require 函數將不把檔案載入到程式中。我們也可以模仿 pwd.pl 的做法編寫自己的庫,然後放在相應的正確目錄下,這樣便可以使用自訂的庫了。在使用自訂的庫時,也不忘記在最後一行寫上 "1;" ,否則會在使用 require 時返回類似的錯誤提示:xxx.pl did not return a true value at xxx.plx lines 5 。
@INC 數組
@INC 是 Perl 內建的一個特殊數組,它包含指向庫常式所在位置的目錄路徑,如果你包含的庫並不在這些目錄之下,那麼可在命令列中使用 -l 選項開關,這點和 gcc 編譯時間使用-L和-l選項使用第三方庫的行為有些類似。@INC對use命令沒用,它只服務於require命令,use命令直接去訪問perl模組目錄(如/usr/lib/perl5/5.6/)
可以用 perl -V 命令看到 @INC 數組的內容:
1 $perl -V2 ...3 @INC:4 /usr/local/lib/perl55 /usr/local/share/perl56 /usr/lib/perl5/vendor_perl7 /usr/share/perl5/vendor_perl8 /usr/lib/perl59 /usr/share/perl5
perl 命令的 -e 選項可以後接命令,這樣可以單獨的列印出 @INC 的內容:
1 $ perl -e 'print "@INC\n"'2 /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .
由上可見,@INC 數組最後一個元素是目前的目錄,如果我們希望將當前工作目錄稱為搜尋路徑中第一個元素,那麼可以使用 unshift (@INC, "."); 來完成。
包的概念
單獨的命名空間又稱為包 (package) 。單獨的命名空間意味著,對於命名包中所有的變數,Perl 都持有一個單獨的符號表。預設情況下,包內所有的變數都是全域變數,而包機制則允許使用者切換命名空間,從而讓保重的變數稱為私人變數,即使它們在包外擁有相同的名稱也可如此。
包的範圍
包的範圍從聲明位置開始直到檔案末尾,或者是最內層封閉塊的末尾,還可以是知道另一個包的聲明為止。聲明另一個包就用 package 函數。在一個包中引用另一個包中的變數,可以在包名前面加上代表VARIANT 資料型別的特殊符號,然後是雙冒號和變數名,如:$friend::name 。
在Perl包間切換及包的引用:
1 #!/usr/bin/perl 2 3 @town = qw(china wencheng qinglan); 4 $friend = "Jasmine"; 5 #在main包中 6 print "In main: \$friend is $friend\n"; 7 #聲明 boy 包,並切換到boy 8 package boy; 9 #$name在boy包中的命名空間裡,和main中的互不干擾10 $name = "Tony";11 print "In boy \$name is $name.\n";12 #使用main包中的$friend,並進行修改13 $main::friend = "Obama";14 print "In boy \@town is @::town\n"; #main包是預設包,不需要寫出main的名字,用@符號代替main15 #切換回main包中16 package main;17 print "In main: \$name is $name\n";18 print "In main: \$main is $boy::name\n";19 print "In main: \$friend is $friend.\n";
運行結果:
1 In main: $friend is Jasmine2 In boy $name is Tony.3 In boy @town is china wencheng qinglan4 In main: $name is5 In main: $main is Tony6 In main: $friend is Obama.
建立一個包及引用包中的子常式:
1 #!/usr/bin/perl2 unshift(@INC,"D:\\perlwork1");3 require "average.pl";4 print "Enter your midterm scores\n";5 6 @scores=split(' ',<STDIN>);7 8 printf "The average is %.lf.\n",average::ave(@scores);#應用程式套件中ave子常式
建立包
1 #!/usr/bin/perl 2 package average 3 sub ave 4 { 5 my (@grades)=@_; 6 my ($num_of_grades)=$#grades+1; 7 foreach $grade( @grades ) 8 { 9 $total +=$grade;10 }11 $total/$num_of_grades;12 }13 1;
模組
Perl5中用Perl包來建立模組,方法是建立Perl包並將之存在同名的檔案中。例如,名為Mymodult的Perl包存貯在檔案Mymodult.pm中(副檔名.pm表示PerlModule)。下例的模組Mymodult含有子程式myfunc1和myfunc2及變數$myvar1和$myvar2。
1 #!/usr/bin/perl 2 package Mymodule; #定義模組名稱 Mymodule.pm 3 require Exporter; #使用Exporter.pm模組將本模組符號匯出到另一個包(載入者) 4 @ISA=qw(Exporter); #@ISA數組含有本模組需要用到的包名,本模組用到模組Exporter.pm 5 #@EXPORT列出了從本模組預設匯出到模組調用者的子常式。myfunc3不在匯出列表(@EXPORT)中,調用者不能直接調用myfunc3。 6 @EXPORT=qw(myfunc1,myfunc2); 7 @EXPORT_OK=qw($myvar1$myvar2); 8 9 sub myfunc110 { 11 $myvar1+=1; 12 } 13 14 sub myfunc215 { 16 $myvar2+=2; 17 } 18 19 sub myfunc320 { 21 $myvar3+=2; 22 }
註:.pm檔案不僅放在perl工作庫目錄,其實放在目前的目錄,也可以直接use