程式扎記: [Perl 學習手冊] CH11 : Perl 模組

標籤

2010年9月11日 星期六

[Perl 學習手冊] CH11 : Perl 模組


前言 :
這裡無法告訴你關於 Perl 的每件事. 只要有問題, 八成都可以在 Perl 綜合典藏網 (CPAN)上找到他人已經寫好的答案. 如果你要學習如何撰寫模組, 羊駝書是不錯的指南. 這裡我們將會教你使用既有的模組.

找到模組 :
模組有兩種散佈方式 : 一類模組隨附在 Perl 發行版本中, 另一類則得從 CPAN 上自行安裝. 除非特別指名, 否則這裡討論的都是 Perl 隨附的模組.
要找到 Perl 未隨附的模組, 就得上 CPAN Search 網站, 或是利用 Kobes's Search 網站. 這兩個網站都是不錯的資源, 你可以直接在上面瀏覽模組的文件, 也可以先看看整個套件裡面的檔案內容, 再判斷要不要下載.
而你在尋找模組之前, 請先檢查一下系統上是否已經有安裝過. 方法之一就是試著以 perldoc 來閱讀該模組的文件. 比方說, Perl 隨附有 CGI.pm 模組, 所以你應該可以直接閱讀它的文件 :
$ perldoc CGI #進入 CGI 文件

試著改成一個不存在的模組名稱, 你會看到一些錯誤訊息 :
$ perldoc Llamas
No documentation found for "Llamas".

安裝模組 :
當你想要自行安裝系統上沒有的模組時, 可以直接下載套件並解開它, 然後再 shell 執行一連串的命令. 套件中 RRADME 和 INSTALL 這兩個檔案, 通常可以看到一些有用的資訊. 如果這個模組使用了 MakeMaker, 那麼你可以多半使用下面的方式來安裝 :
$ perl Makefile.PL
$ make install

如果你不具備將模組安裝到系統目錄的權限, 則可以為 Makefile.PL 加上一個 PREFIX 引數, 以便指定其他的安裝目錄 :
$ perl Makefile.PL PREFIX=/Users/john/lib

有些 Perl 模組的作者會使用另一個模組, Module::Build , 來編譯並安裝他們的作品, 此時安裝的方是大略如下 :
$ perl Build.PL
$ ./Build install

然而有些模組依賴其他的模組, 所以你必須事先安裝更多的模組, 它們才會正常運作. 與其自己動手一個個來, 不如使用 Perl 隨附的 CPAN.pm 來進行. 你可以在命令列啟動 CPAN.pm 自己的 shell, 以便下達相關命令 :
$ perl -MCPAN -e shell

這樣寫起來稍嫌複雜, 有個小小的程式叫做 cpan 隨附在 Perl 裡, 通常跟 perl 安裝再一起, 只要把想安裝的模組當作參數傳給它就行了 :
$ cpan Module::CoreList LWP CGI::Prototype

使用簡單的模組 :
假設你在程式裡碰上一個冗長的檔案全名, 像是 E:\Temp\Auto\test.txt , 而你想取得基本檔名. 這並不難, 因為在一個倒斜線之後就是基本檔名 :
  1. my $name = "E:\\Temp\\Auto\\test.txt";  
  2. (my $basename = $name) =~ s/.*\\//;  
  3. print "File name=$basename\n";  
如你所見, Perl 會先在圓括號賦值, 接著進行替換. 接著任何結尾為倒斜線的字串 (也就是目錄名稱的部分) 都會被置換成空字串只留下基本檔名.
試試看似乎可行, 但是有三個問題. 首先 Unix 檔案或目錄可包含換列字符 (這不常發生, 但可能). 由於正規表示式的點號 (.) 無法匹配換列字符, 所以上面程式可能無法運作. 但你可以使用 /s 選項加以修正. 第二個問題是 Unix 特有的. 它會認為目錄分隔符號是 Unix 上所使用的斜線, 而非某些系統所使用的斜線或冒號. 第三個問題 (也是最大的) 是我們正試圖解決別人已經解決的問題. Perl 隨附了相當數量的模組. 模組是聰明的延伸套件, 可用來增進 Perl 本身的功能. 若這還不夠, CPAN 上有更多好用的模組可以參考. 必要時你可以安裝它們. 之後的內容我們會討論如何使用某些 Perl 隨附模組的功能.

- File::Basename 模組
前面的範例中, 我們用了不具移植性的方式來取得基本檔名. 這種方法看起來容易了解, 但可能因為環境不同而有出乎預期的結果. 要從檔案全名裡取出主檔名, 這裡有個比較好的做法, 就是使用 Perl 隨附的 File::Basename 模組. 只要執行 perldoc File::Basename 這道命令, 或是透過系統上的文件機制, 你就能看到它的使用說明. 這是使用模組的第一步. 當你要使用它時, 請在程式開頭以 use 指令來宣告它 :
use File::Basename

Perl 在編譯階段會看到這段程式碼, 並且載入模組, 這樣一來 Perl 就好像多出一些函式, 讓你在接下來的程式可以使用. 前面的例子我們需要的正是 basename 函式 :
  1. my $name = "E:\\Temp\\Auto\\test.txt";  
  2. my $basename = basename $name;  
  3. print "File name=$basename\n";  
雖然在 Windows 上面行的通, 但如果我們程式在 MacPerl, Unix 等系統上執行呢? 不用擔心, 這個模組會判斷你用的是哪種系統, 並且使用該系統預設的檔名規則. 此模組還提供一些相關函式, 其中的 dirname 函式, 可以從檔案全名裡取得目錄名稱. 更多請使用 perldoc 參考使用說明.

- 只選用模組中部分的函式
假設你想在寫好的程式裡加上 File::Basename 模組, 卻發現程式裡已經有個叫做 &dirname 的副常式 - 也就是說程式自訂義的函式名稱與模組既有函式名稱衝突怎麼辦? 很簡單, 只要在 File::Basename 的宣告裡加入匯入串列 (import list), 指名要它提供哪些函式, 它就不會給你別的函式了, 在此我們只需要 basename 函式 :
use File::Basename qw / basename /;

底下的寫法表示我們完全不需要任何新的函式 :
use File:Basename qw/ /;

而這也常寫成 :
use File::Basename ();

為什麼要這麼做呢 ? 上面的寫法會讓 Perl 載入 File::Basename 卻不匯入 (import) 任何函式名稱. 匯入的動作可讓我們使用簡短的函式名稱, 像是 baename 和 dirname. 然而即使不匯入這些名稱, 我們還是可以呼叫相應的函式. 在沒有匯入的情況下, 我們必須使用全名來呼叫函式 :
my $name = "/usr/local/bin/perl";
my $dirname = File::Basename::dirname $name
 # 使用模組的 dirname

如你所見, 模組裡 dirname 函式的全名是 File::Basename::dirname. 載入模組後, 無論是否匯入 dirname 這種簡短的名稱, 我們隨時可以使用函式的全名. 大多數情況下, 你將會想要使用模組預設的匯入串列. 不過要是你想要省略某些預設的項目, 也隨時可以用自己定義的串列來蓋過它. 自己指定匯入串列的另一個理由是, 想要匯入不在預設串列裡的函式 ; 大多數模組的預設匯入串列裡, 都會省略某些不常用的函式. 而所有模組的說明文件都應該列出它可供匯入的符號, 但是你隨時都可以蓋過預設的匯入串列.

- File::Spec 模組
現在你可以取得基本檔名. 雖然很有用, 不過你常常還必須將它和目錄名稱結合, 以取得檔案的全名. 例如我們想取得 /home/rootbeer/ice-2.1.txt 這樣的檔案全名, 並對其基本檔名加上前置字串 :
  1. use File::Basename;  
  2.   
  3. print "Key in: ";  
  4. chomp(my $old_name = );  
  5. my $dirname = dirname $old_name;  
  6. my $basename = basename $old_name;  
  7. $basename =~ s/^/not/;  
  8. my $new_name = "$dirname/$basename";  
  9. print "Result=$new_name\n";  
你可以利用 File::Spec 模組來操作檔案細節, 也就是檔名, 目錄以及檔案系統的其他名稱. 它和 File::Basename 一樣會在執行時判斷系統的類型, 並採取正確的規則. 另外 File::Spec 是物件導向的模組, 而在這個例子裡, 根據 File::Spec 說明文件, 我們應該使用一個稱為 catfile 的方法從 Fiile::Spec 來叫用它時, 你一定得使用全名 ; 這和普通的函式不同. 用法如下 :
use File::Spec
... # 取得 $dirname 和 $basename 的值
my $new_name = File::Spec->catfile($dirname, $basename);

方法的全名組成自模組的名稱 (此處稱為類別) , 一個小箭號 (->) 以及方法的簡短名稱. 既然我們得用全名來叫用方法, 那麼模組會匯入哪些符號呢? 答案是什麼都沒有的, 對有 OO 模組來說, 這是正常的做法. 這樣一來你就不必擔心自己的副常式會跟 File::Spec 裡眾多方法重覆.
This message was edited 4 times. Last update was at 02/09/2010 21:54:04

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!