第一章 概述

【 require函數 】
    用require函數可以把程序分割成多個文件並創建函數庫。例如,在myfile.pl中有定義好的Perl函數,可用語句require ("myfile.pl"); 在程序中包含進來。當Perl解釋器看到這一語句,就在內置數組變量@INC指定的目錄中尋找文件myfile.pl。如果找到了,該文件中的語句就被執行,否則程序終止並輸出錯誤信息︰
    Can't find myfile.pl in @INC
    作為子程序調用參數,文件中最後一個表達式的值成為返回值,require函數查看其是否為零,若為零則終止。例如myfile.pl最後的語句是︰
    print ("hello, world!\n");
    $var = 0;
    因為最後的語句值為零,Perl解釋器輸出下列錯誤信息並推出︰
    myfile.pl did not reture true value
    可以用簡單變量或數組元素等向require傳遞參數,如︰
@reqlist = ("file1.pl", "file2.pl", "file3.pl");
require ($reqlist[$0]);
require ($reqlist[$1]);
require ($reqlist[$2]);
    還可以不指定文件名,即︰
    require;
    這時,變量$_的值即作為文件名傳遞給require。
    注︰如果@INC中有多個目錄中含有同一個文件,則只有第一個被包含。
1、require函數和子程序
    用require函數可以創建可用於所有Perl程序的子程序庫,步驟如下︰
a、確定存貯子程序庫的目錄
b、將子程序抽取放到單獨的文件中,將文件放到子程序庫目錄
c、每個文件末尾加一句非零值的語句,最簡單的辦法是語句 1;
d、在主程序中用require包含一個或多個所需的文件。
e、運行主程序時,用 -I 選項指定子程序庫目錄,或者在調用require前將該目錄添加到@INC數組中。
    例如︰假設目錄/u/perldir中存有你的Perl子程序庫,子程序mysub存貯在文件mysub.pl中。現在來包含上該文件︰
    unshift (@INC, "/u/perldir");
    require ("mysub.pl");
    對unshift的調用把目錄/u/perldir添加到@INC數組,對require的調用將mysub.pl文件的內容包含進來作為程序的一部分。
注意︰
1、應該使用unshift來向@INC中添加目錄,而不是push。因為push增加到@INC的末尾,則該目錄將被最後搜尋。
2、如果你的庫文件名與/usr/local/lib/perl中的某文件同名,則不會被包含進來,因為require只包含同名文件中的第一個。
2、用require指定Perl版本
    Perl 5中,可以用require語句來指定程序運行所需的Perl版本。當Perl解釋器看到require後跟著數字時,則只有其版本高於或等於該數字時才運行該程序。例如,下面語句表明只有Perl解釋器為5.001版或更高時才運行該程序︰
    require 5.001;
【 包 】
    Perl程序把變量和子程序的名稱存貯到符號表中,perl的符號表中名字的集合就稱為包(package)。
1、包的定義
    在一個程序中可以定義多個包,每個包有一個單獨的符號表,定義語法為︰
    package mypack;
    此語句定義一個名為mypack的包,從此以後定義的所有變量和子程序的名字都存貯在該包關聯的符號表中,直到遇到另一個package語句為止。
    每個符號表有其自己的一組變量、子程序名,各組名字是不相關的,因此可以在不同的包中使用相同的變量名,而代表的是不同的變量。如︰
$var = 14;
package mypack;
$var = 6;
    第一個語句創建變量$var並存貯在main符號表中,第三個語句創建另一個同名變量$var並存貯在mypack包的符號表中。
2、在包間切換
    在程序裡可以隨時在包間來回切換,如︰
1: #!/usr/local/bin/perl
2:
3: package pack1;
4: $var = 26;
5: package pack2;
6: $var = 34;
7: package pack1;
8: print ("$var\n");
    運行結果如下︰
$ program
26
$
    第三行定義了包pack1,第四行創建變量$var,存貯在包pack1的符號表中,第五行定義新包pack2,第六行創建另一個變量$var,存貯在包pack2的符號表中。這樣就有兩個獨立的$var,分別存貯在不同的包中。第七行又指定pack1為當前包,因為包pack1已經定義,這樣,所有變量和子程序的定義和調用都為該包的符號表中存貯的名字。因此第八行對$var的調用為pack1包中的$var,其值為26。
3、main包
    存貯變量和子程序的名字的缺省符號表是與名為main的包相關聯的。如果在程序裡定義了其它的包,當你想切換回去使用缺省的符號表,可以重新指定main包︰
    package main;
    這樣,接下來的程序就好象從沒定義過包一樣,變量和子程序的名字象通常那樣存貯。
4、包的引用
    在一個包中可以引用其它包中的變量或子程序,方法是在變量名前面加上包名和一個單引號,如︰
package mypack;
$var = 26;
package main;
print ("$mypack'var\n");
    這裡,$mypack'var為mypack包中的變量$var。
    注意︰在Perl 5中,包名和變量名用雙冒號隔開,即$mypack::var。單引號引用的方式仍然支持,但將來的版本中未必支持。
5、指定無當前包
    在Perl 5中,可以用如下語句指定無當前包︰
     package;
    這時,所有的變量必須明確指出所屬包名,否則就無效--錯誤。
     $mypack::var = 21; #ok
     $var = 21;   #error - no current package
    這種情況直到用package語句指定當前包為止。
6、包和子程序
    包的定義影響到程序中的所有語句,包括子程序,如︰
package mypack;
subroutine mysub {
  local ($myvar);
  # stuff goes here
}
    這裡,mysub和myvar都是包mypack的一部分。在包mypack外調用子程序mysub,則要指定包︰$mypack'mysub。
    可以在子程序中切換包︰
package pack1;
subroutine mysub {
  $var1 = 1;
  package pack2;
  $var1 = 2;
}
    這段代碼創建了兩個變量$var1,一個在包pack1中,一個在包pack2中,包中的局域變量只能在其定義的子程序等語句塊中使用,像普通的局域變量一樣。
7、用包定義私有數據
    包最通常的用途是用在含有子程序和子程序所使用的全局變量的文件中,為子程序定義這樣的包,可以保証子程序使用的全局變量不可在其它地方使用,這樣的數據即為私有數據。更進一步,可以保証包名不可在其它地方使用。私有數據例︰
1 : package privpack;
2 : $valtoprint = 46;
3 :
4 : package main;
5 : # This function is the link to the outside world.
6 : sub printval {
7 :   &privpack'printval();
8 : }
9 :
10: package privpack;
11: sub printval {
12:   print ("$valtoprint\n");
13: }
14:
15: package main;
16: 1; # return value for require
    此子程序只有在調用printval後才能產生輸出。
    該文件分為兩個部分︰與外界聯系的部分和私有部分。前者為缺省的main包,後者為包privpack。第6~8行定義的子程序printval可被其它程序或子程序調用。printval輸出變量$valtoprint的值,此變量僅在包privpack中定義和使用。第15、16行確保其被其它程序用require語句包含後工作正常,15行將當前包設置回缺省包main,16行返回非零值使require不報錯。
8、包和系統變量
    下列變量即使從其它包中調用,也在main包中起作用︰
  • 文件變量STDIN, STDOUT, STDERR 和 ARGV
  • 變量%ENV, %INC, @INC, $ARGV 和 @ARGV
  • 其它含有特殊字符的系統變量
9、訪問符號表
    在程序中查找符號表可用數組%_package,此處package為想訪問的符號表所屬的包名。例如%_main含有缺省的符號表。
    通常不需要親自查找符號表。
【 模塊 】
    多數大型程序都分割成多個部件,每一部件通常含有一個或多個子程序及相關的變量,執行特定的一個或多個任務。集合了變量和子程序的部件稱為程序模塊。
1、創建模塊
    Perl 5中用包來創建模塊,方法是創建包並將之存在同名的文件中。例如,名為Mymodult的包存貯在文件Mymodult.pm中(擴展名.pm表示Perl Module)。下例的模塊Mymodult含有子程序myfunc1和myfunc2及變量$myvar1和$myvar2。
1 : #!/usr/local/bin/perl
2 :
3 : package Mymodule;
4 : require Exporter;
5 : @ISA = qw(Exporter);
6 : @EXPORT = qw(myfunc1 myfunc2);
7 : @EXPORT_OK = qw($myvar1 $myvar2);
8 :
9 : sub myfunc1 {
10:   $myvar1 += 1;
11: }
12:
13: sub myfunc2 {
14:   $myvar2 += 2;
15: }
    第3~7行是標準的Perl模塊定義方式。第3行定義包,第4行包含內置Perl模塊Exporter,6、7行進行子程序和變量的輸出以與外界聯系。第6行創建名為@EXPORT的特殊數組,該數組中的子程序可以被其它程序調用,這裡,myfunc1和myfunc2可以被訪問。其它任何在模塊中定義但沒有賦給數組@EXPORT的子程序都是私有的,只能在模塊內部調用。第7行創建另一個名為@EXPORT_OK的特殊數組,其中含有可被外部程序訪問的變量,這裡含有$myvar1和$myvar2。
2、導入模塊
    將模塊導入你的Perl程序中使用use語句,如下句導入了Mymodule模塊︰
     use Mymodule;
    這樣,模塊Mymodule中的子程序和變量就可以使用了。
    取消導入模塊使用no語句,如下句取消了Mymodule模塊的導入︰
     no Mymodule;
    下面看一個導入模塊和取消導入的例子,使用integer模塊要求所有數字運算基於整數,浮點數在運算前均被轉化為整數。
1: #!/usr/local/bin/perl
2:
3: use integer;
4: $result = 2.4 + 2.4;
5: print ("$result\n");
6:
7: no integer;
8: $result = 2.4 + 2.4;
9: print ("$result\n");
    程序輸出如下︰
$ program
4
4.8
$
    如果use或no語句出現在語句塊中,則只在該塊的有效范圍內起作用,如︰
use integer;
$result1 = 2.4 + 2.4;
if ($result1 == 4) {
no integer;
$result2 = 3.4 + 3.4;
}
$result3 = 4.4 + 4.4;
    結果輸出如下︰
4
6.8
8
    這裡,no語句只在if語句中有效,出了if語句仍使用integer模塊,因此4.4在做加法前被轉化成了4。
3、預定義模塊
    Perl 5提供了許多有用的預定義模塊,可以用use導入和no語句取消。下面是庫中最有用的一些模塊︰
integer使用整數運算
Diagnostics  輸出較多的診斷信息(警告)
English允許英文名用作系統變量的別名
Env導入環境變量的Perl模塊
POSIXPOSIX標準(IEEE 1003.1)的Perl接口  
Socket裝載C語言的套接字處理機製
    Perl文檔中有完整的預定義模塊列表。
    注︰世界各地的Perl 5用戶寫了許多有用的模塊,CPAN(Comprehensive Perl Archive Network)的Perl文檔有其完整的列表。關於CPAN的更多信息見其網址︰http://www.perl.com/perl/CPAN/README.html

CopyRight © 2001 All Rights Reserved