位元詩人 [Perl] 程式設計教學:基本觀念

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

本文假定讀者沒有寫過 Perl 程式或僅寫過少量 Perl 程式,從頭介紹一些撰寫 Perl 程式相關的基本概念和工具,讓讀者可以開始撰寫 Perl 程式。

Perl 程式碼的副檔名

獨立的 Perl 命令稿以 .pl 為副檔名,Perl 模組則以 .pm 為副檔名,而 Perl 延伸模組則以 .xs 為副檔名。只有文件的 Perl 命令稿會用 .pod 為副檔名。測試程式會以 .t 為副檔名。

執行 Perl 程式的方式

Perl 程式有兩種執行方式:

  • 撰寫 Perl 命令稿後,執行該命令稿
  • 從命令列直接執行 Perl 程式 (即 Perl one-liner)

第一種方式是大部分高階直譯語言都會採用的方式,但第二種方式則相對少見,由於 Perl 兩者兼具,故筆者認為 Perl 做為一個命令列工具仍然有其一定的價值。

在本文中,我們會用這兩種方式各寫一個 Hello World 程式,以熟悉撰寫 Perl 程式的方式。

使用命令稿寫 Hello World 程式

Hello World 程式是用來熟悉開發流程的經典範例,原見於經典的 The C Programming Language ,此處撰寫 Perl 的版本。

Windows

使用編輯器撰寫 hello.pl 程式,加入以下程式碼:

print "Hello World\n";

不用在意程式的細節,我們只是要確認程式可執行。

使用以下指令來執行該命令稿:

> perl hello.pl
Hello World

若出現 Hello World 訊息,代表程式執行成功;若沒有執行成功,需自行根據錯誤訊息來除錯。

Unix

如果讀者使用類 Unix 系統,可以把 Perl 命令稿製作成命令列程式。略為修改一下 hello.pl 的內容:

#!/usr/bin/env perl

print "Hello World\n";

我們額外加入的一行稱為 she bang。對 Perl 來說,該行只是註解,但類 Unix 系統會根據該行的內容啟動該行所指定的直譯器。以本例來說,就是啟動 Perl。

把該命令稿加上可執行的權限:

$ chmod +x hello.pl

執行該命令稿:

$ ./hello.pl
Hello World

這裡有用到類 Unix 系統的特性,在 Windows 上則無法使用這個方法。

使用命令列即時撰寫 Hello World 程式

以下是直接使用命令列撰寫 Hello World 程式的版本:

$ perl -e 'print "Hello World\n";'
Hello World

在 Windows 則要稍微修改一下:

> perl -e "print \"Hello World\n\";"
Hello World

這是因為命令提示字元的字串只能用雙引號括起來的緣故,所以在 Windows 寫 Perl one-liner 會稍微麻煩一點。

Perl one-liner 有許多使用方式,國外也出過一些相關的專書。Perl one-liner 主要是用在命令列上即時輸入一些短小的 Perl 程式,如果發現 Perl one-liner 可能會很長時,最好就轉成命令稿的形式來寫。

再訪 Hello World

我們再看一次 Hello World:

print "Hello World\n";

Perl 和 C 或 Java 不同,沒有主函式 (main function) 的概念,執行某個命令稿時,該命令稿本身等同於主函式。

print 是 Perl 的內建函式 (builtin functions),功能為在終端機輸出字串,由於 print 尾端不會自動加入換行符號,故需自行加入。內建函式是一些預寫好的 Perl 程式,只要呼叫該函式,即可立即獲得所需的功能。函式使用者不需在意這些函式內部的實作,只要將其視為一些立即可用的指令即可。

在使用 Perl 函式時,可以省略括號,這時候函式看起來會很像 Perl 內建語法。Perl 刻意不嚴格區分函式和語法,雖然寫起來比較簡便,但有時也會造成混淆,所以筆者不建議使用 Perl 開發中大型程式。

使用嚴格模式

一開始在撰寫 Perl 命令稿時,會建議在命令稿的開頭加上以下 pragmas:

use strict;
use warnings;

Pragmas 用來改變 Perl 的行為。以 use strict; 來說,會禁止一些過於鬆散的語法,而 use warnings; 會開啟較多的警告訊息。

一開始練習撰寫 Perl 程式時,最好一律加上這兩個 pragmas,以免養成不良的撰碼習慣。等寫熟了之後,要寫一些用完即丟的命令稿或是 Perl one-liner 時,就不一定要加入這些 pragmas。

Perl 的程式碼風格

Perl 官方文件有建議的程式碼風格,可以讀一下,一開始完全沒學過 Perl 時可能無法吸收,可過一陣子再回頭看。

O'Reilly 曾出過一本 Perl Best Practices (中譯已絕版),裡面有更多關於撰寫 Perl 程式的建議。這本書提供許多不錯的建議,但在某些面向主觀過強,不需照單全收。

perlcritic 是一個以 Perl 寫成的 Perl 程式碼檢查軟體,會對 Perl 程式碼進行撰寫上的建議。在 perlcritic 程式中有實作一些來自 Perl Best Practices 的建議事項。

重排 Perl 程式碼

perltidy 是一個 Perl 程式碼重排工具,可以省下手動整理程式碼的工夫。該軟體有一些細項可以調整,有需要的讀者可自行閱讀其手冊。

Perl 的文件

Perl doc 網站收錄最新版本的 Perl 的官方文件。對於 Perl 學習者來說,應該要習慣去查閱這個網站的內容。

除了使用該網站外,perldoc 是一個隨 Perl 發佈的命令列工具,其用途是在本地端查詢 Perl 文件。

使用 perldoc -f 可以查詢 Perl 內建函式 (built-in function) 的用法:

$ perldoc -f sprintf

使用 perldoc -v 可以查詢 Perl 內建變數 (built-in variable) 的用法:

$ perldoc -v '$"'

查詢 Perl 內建變數算是蠻實用的功能。因為許多 Perl 內建變數是以非文字符號的方式來表示,使用一般的搜尋引擎不易搜尋。

perldoc 也可查詢模組名稱:

$ perldoc Moo

至於其他的用法,請閱讀 perldoc 本身的文件。

使用 Perl 撰寫命令列程式

在類 Unix 系統上,在命令稿的最開頭使用 #! (shebang) 可以讓命令稿變成命令列工具。例如以下的命令稿:

#!/usr/bin/perl

print "Hello World\n";

在本例中,該命令稿藉由 shebang 提示系統,使用位於 /usr/bin/perl 的執行檔執行本命令稿。

只要給予該命令稿可執行 (executable) 的權限即可執行此命令稿:

$ chmod +x hello.pl
$ ./hello.pl
Hello World

由於類 Unix 系統的終端機環境不以副檔名判斷程式,連 .pl 都可以省略,這樣該命令稿看起來就和其他命令列工具無異。

由於 Windows 系統沒有 shebang 的特性,這個方法在 Windows 上無效。而且在 Windows 上的 Perl (或其他直譯語言) 命令稿還是要保留副檔名較好,因為 Windows 需要用副檔名來判斷檔案的執行方式。

撰寫具有可攜性的 Perl 命令稿

前述的命令稿將 Perl 路徑寫死,可攜性較差。一般來說,我們會用 env(1) 工具自動判定 Perl 路徑,以改善可攜性:

#!/usr/bin/env perl

foreach my $a (@ARGV) {
    print "$a\n";
}

然而,使用 env 時,perl 指令後只能帶單一參數,這是 env 所帶來的限制。在 Perl 命令稿中,使用多參數的情形並不少見。我們可以用 shell 命令稿做為 wrapper 來改善這個問題:

#!/bin/sh

# Embed a Perl script in a shell script
cat << 'SCRIPT' | perl - "$@"
foreach my $a (@ARGV) {
    print "$a\n";
}
SCRIPT

一開始系統會將該命令稿判定為 sh 命令稿,但我們在該命令稿中內嵌 (embedding) Perl 命令稿,再呼叫 perl 去執行該內嵌的命令稿。如果需要多個參數,將所需的參數直接寫入此命令稿即可。我們藉由 $@ 變數帶入外部的參數,所以該命令稿使用起來和一般的命令列工具無異。

使用 shell wrapper 的缺點在於編輯器無法辨識內嵌的 Perl 命令稿,不會將該內嵌命令稿加上語法高亮,可維護性會略差一些。

由於 Windows 系統沒有 env(1) 也不支援 sh(1),故無法使用本節所提到的技巧。

線上執行 Perl 程式

以下是一些可透過瀏覽器執行 Perl 程式的線上平台:

這些平台當然無法取代真正的開發環境,但可用在學習 Perl 基本語法。

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。