Perl

Perl是高階、通用、直譯式、動態的程式語言家族。最初設計者拉里·沃爾為了讓在UNIX上進行報表處理的工作變得更方便，決定開發一個通用的腳本語言，而在1987年12月18日發表。目前，Perl語言家族包含兩個分支Perl 5以及Raku。

關於Perl名字的由來，有很多說法。雖然Perl不是正式的首字母縮略詞，但仍有各種各樣的逆向首字母縮略詞，包括「實用的提取和報告語言」。

Perl借用了C、sed、awk、shell腳本、Lisp以及很多其他程式語言的特性。其中最重要的特性是Perl內部集成了正則表達式的功能，以及巨大的第三方代碼庫CPAN。

2000年開始，拉里·沃爾著手開發Perl 6來作為Perl的後繼，Perl 6語言的語法有很多轉變，也被視為Perl家族中的另一個語言（Perl 6於2019年更名為Raku）。

Perl語言應用廣泛，涵蓋CGI、圖形編程、系統管理、網路編程、金融、生物等領域。由於其靈活性，Perl被稱為腳本語言中的瑞士軍刀。

## 歷史

### 早期版本

拉里·沃爾在1987年開始寫作Perl，那時他正在Unisys當程式設計師，並且在1987年12月18日把1.0版本發布到了comp.sources.misc新聞組。這個語言在接下來的幾年內很快地發展起來。

沃爾最早的確把這個語言稱為「Pearl」（珍珠），因為他希望自己開發的語言有一個吉利的名字而且要儘量短小好記，他甚至聲稱早已考慮過所有三個及四個字母的詞彙，以及自己妻子的名字Gloria。然而另一門語言PEARL早已存在，為了防止混淆，沃爾才把它改名Perl。

Perl 2，於1988年發布，特色是有一個更好的正則表達式引擎，Perl 3，於1989年發布，添加了對二進位數據流的支持。

從前，Perl唯一的文檔是一個逐漸變長的手冊頁。在1991年，《Programming Perl》（被許多Perl程式設計師因封面稱為「駱駝書」），出版了，而且變成了一個真正的Perl語言的參考資料。同時，Perl版本號變成了4，不是因為這個語言的重大改變，而是因為這本書的特殊意義。

### 早期的Perl 5

Perl 4的一系列維護的版本，最後一版是1993年的Perl 4.036。那時，沃爾廢棄了Perl 4，開始開發Perl 5。Perl 5的最初始設計持續到了1994年。《perl5-porters》郵件列表於1994年5月為了共同移植Perl 5而建立。這將主要的論壇留給了Perl 5的開發，維護，和移植。

Perl 5.000於1994年10月17日發布。這是一個幾乎完全重寫了的解釋器，而且它給這個語言添加了很多新的特性，包括對象，引用，局部變量，和模塊。很重要地，模塊提供了一個不用修改直譯器就可以擴展語言的方法。這使得核心的直譯器非常穩定，即使它允許一般的Perl程式設計師添加新的語言特性。從此，Perl 5的開發就活躍起來了。

Perl 5.001於1995年3月13日發布。Perl 5.002於1996年2月29日發布，帶有參數類型的特性。這允許模塊的作者寫出像Perl內部命令那樣智能的子程序。Perl 5.003於1996年6月25日作為一個安全更新的版本發布。

Perl 5歷史中最重要的事件之一是支持了模塊。在1995年10月26日，CPAN，一個發布Perl模塊的網站，建立了；截至2015年11月，它已經有超過12457個作者寫的157794多個模塊了。

Perl 5.004於1997年5月15日發布，添加了UNIVERSAL包，這給了Perl一個所有的類的基礎和要求使用模塊的特定版本的能力。另一個重要的開發是包括了CGI.pm模塊，有助於Perl發展為一個CGI腳本語言。

Perl具有優秀的跨平台特性。Perl現在支持在Microsoft Windows、蘋果公司的MacOS、GNU/Linux和其它一些作業系統下運作。

Perl 5.005於1998年7月22日發布。這個版本包括了一個更好的正則引擎，一個編譯系統（通過`B::*`模塊），`qr//`正則引用操作符，一個基礎模塊的選集，並且又支持了一些其它的作業系統，包括BeOS。

### 2000年至今

主要版本｜最後更新

o｜2004年2月23日

o o o o o o o o o o o o o o o o o c

Perl 5.6於2000年3月22日發布。大的修改包括64位支持，Unicode字串支持，大文件支持（即：超過2GiB的文件）以及「our」關鍵字。在開發Perl 5.6的時候，開發組決定把版本名稱作成類似其它開源項目的；在5.005_63版之後，下一個版本變成了5.5.640，計劃是開發版本用奇數，穩定版本用偶數。

2000年時，拉里·沃爾詢問社區對Perl新版本的建議。這個進程的結果在361 RFC（評論請求）文件里（這個文件可以指導Perl 6的開發）。2001年，工作開始於設計Perl 6，一系列的文件概述了新一代Perl里的改變和設計。它們是作為一期RFC被展示的，而不是一個正式文檔。這時，Perl 6的存在還只是一門語言的概述。

Perl 5.8最初於2002年7月18日發布，從此，每年才有一次更新。Perl 5.8的最後一版是5.8.9，發布於2008年12月14日。Perl 5.8改進了Unicode支持，添加了一個新的IO處理機制和新的多線程處理，提高了數字精度，添加了一些新模塊。

2004年，工作開始於提要——原來的建議文件，但後來變成了Perl 6語言的詳述。2005年2月，唐鳳，開始開發Pugs，一個用Haskell寫的Perl 6直譯器。這是最初的一個Perl 6實現。這個努力止於2006年。

2007年12月18日，Perl 1.0的20周年紀念日，Perl 5.10.0發布了。Perl 5.10.0包括了顯著的新特性，這拉近了Perl 5和6之間的距離。這些特性包括一個switch語句（叫做「given/when」），正則表達式的更新和智能匹配操作符「~~」。同時，另一個Perl 6的實現，Rakudo Perl的開發開始了，一起使用Parrot虛擬機開發。從2009年11月開始，Rakudo Perl已經是每月一更新，現在已經是Perl 6的最完整的一個實現了。

Perl 5開發過程中的一次大修改在Perl 5.11；開發社區使用了每月更新的形式，這樣就可以提前預知3個月以內的發布日期。

2010年4月12日，Perl 5.12.0發布了。顯著的提升包括新的`package NAME VERSION`語法，Yada Yada操作符（有意地用占位符標記沒有實現的代碼），默認`use strict;`（在`use 5.012;`時）完整的Y2038編譯，正則轉化重載，DTrace支持，和Unicode5.2。Perl 5.12.3於2011年1月21日發布；它包括了新版的模塊和一些文檔的改變。版本5.12.4於2011年6月20日發布。

Perl 5.14發布於2011年5月14日。這個分支的最後一版，5.14.2，發布於2011年9月26日。

Perl 5.16發布於2012年5月20日。顯著的新特性包括可以指定一個perl的版本來模擬，這允許用戶更新perl的版本，但可以運行可能會不兼容的老腳本。Perl 5.16也更新了核心部分來支持Unicode 6.1。

### 名稱

Perl原名叫「Pearl」。拉里·沃爾想給這個語言起一個有正面意思的短的名字；他考慮了（並且否定了）字典里每一個3—4個字母的詞。他也考慮用他的妻子Gloria的名字命名。沃爾在Perl官方發布之前發現了已存在PEARL語言，於是改成了現在Perl這個名字。

當指代這個語言的時候，名字通常是大寫的（Perl），就像專有名詞一樣。當指代這個直譯器本身的時候，這個名字通常是小寫的（perl），因為大部分類Unix文件系統都是區分大小寫的。在《Programming Perl》的第一版發布之前，用perl指代這個語言也很普遍；Randal L. Schwartz排版時將這個語言的名字在書中寫成大寫的以便理解。後來，這個大小寫的區別就成為正規的了。

全大寫的「PERL」是有爭議的，而文檔中說明「PERL」是不對的，一些核心的社區成員將其視為外行的標誌。這個名字偶爾會被視為「Practical Extraction and Report Language」的縮寫，就像文檔頂端和一些紙質書本說的那樣。一些全稱被建議作為正式名稱，包括沃爾自己的幽默的「Pathologically Eclectic Rubbish Lister」。的確，沃爾要求這個名字啟示許多不同的擴展。

### 駱駝標誌

<image>

《Programming Perl》，由奧萊利媒體發布，特色是封面有一張駱駝的圖片，因而被稱作「駱駝書」。這張駱駝的圖片已經成為了Perl非官方的標誌和一個黑客的標誌，這出現在T恤衫和其它衣服上。

奧萊利擁有此圖像之商標，並且宣稱，唯有在捍衛「符號之完整性」時，才會行使其法律上的權力。奧萊利允許此商標在非商業目的之前提下被使用，並同時供了Programming Republic of Perl的圖像以及Powered by Perl的按鈕圖。Perl的另一個識別符號是羊駝。因為《Intermediate Perl》一書的封面是一隻羊駝。

#### 洋蔥標誌

<image>

Perl基金會擁有一個可選的標誌，一個洋蔥，允許它的子站點，Perl Mongers，PerlMonks，Perl.org和其它網站使用。

## Perl簡介

### Perl語言的中心思想

Perl語言的中心思想可以集成為一句話「TMTOWTDI」：

There's More Than One Way To Do It.（不只一種方法來做一件事。）

Perl的作者拉里·沃爾建議可以把這個縮寫詞念成「Tim Toady」。這句話後來被擴充成:

There's more than one way to do it, but sometimes consistency is not a bad thing either.（不只一種方法來做一件事，但有時保持一致也不錯。）

- TIMTOWTDIBSCINABTE，發音為「Tim Toady Bicarbonate」.

另一個Perl程式設計師常常想起的Perl俗語是：

Easy things should be easy, and hard things should be possible.（簡單的事情應該是簡單的，複雜的事情應該儘可能地變得簡單。）

### 優點

Larry Wall本人也是一個語言學家，他設計Perl語言時使用了很多語言學的思維。相比C、Pascal這樣的「高級」語言而言，Perl語言直接提供泛型變數、動態數組、Hash表等更加便捷的編程元素。Perl具有動態語言的強大靈活的特性，並且還從C/C++、Basic、Pascal等語言中分別借鑑了語法規則，從而提供了許多冗餘語法。使得程式設計師可以忽略電腦內部資料存儲、類型、處理方法、運算規則、甚至記憶體越界等等的細節，而將思考中心放在所需要的程序邏輯上。就這一點而言，很多Perl程式設計師認為目前只有Perl、Python等泛型語言才能稱為「高級」語言，而C、Pascal甚至C++這些只能稱為「中高級」語言而已。可以說，在統一變數類型和掩蓋運算細節方面，Perl做得比Python更為出色。

由於從其他語言大量借鑑了語法，使得從其他程式語言轉到Perl語言的程式設計師可以迅速上手撰寫程序並完成任務。這使得Perl語言是一門容易使用的電腦程式語言。

### 缺點

也正是因為Perl的靈活性和「過度」的冗餘語法，也因此獲得了僅寫（write-only）的「美譽」，因為Perl程式可以寫得很隨意（例如，變數不經宣告就可以直接使用），但是可能少寫一些字母就會得到意想不到的結果（而不報錯），許多Perl程式的程式碼令人難以閱讀，實現相同功能的程序代碼長度可以相差十倍百倍，這就令程式的維護者（甚至是編寫者）難以維護。

同樣的，因為Perl這樣隨意的特點，可能會導致一些Perl程式設計師遺忘語法，以至於不得不經常查看Perl手冊。對此，《Learning Perl》一書裡建議經常使用Perl編程。建議的解決方法是在程序裡使用`use strict;`以及`use warnings;`，並統一代碼風格，使用庫，而不是自己使用「硬編碼」。Perl同樣可以將代碼書寫得像Python或Ruby等語言一樣優雅。

## Perl的語法

### Perl的Hello World程式

下面是一個在標準輸出設備上輸出Hello World的簡單程式，這種程式通常作為開始學習程式語言的第一個範例：

```perl
#!/usr/bin/env perl
print "Hello, world!\n";
```

如果有perl 5.10以上的版本，也可以這樣：

```perl
#!/usr/bin/env perl
use 5.010;
say "Hello, world!";
```

這個程序將輸出一行字串：「Hello, world!」，以及一個換行。

### 變量

Perl是一種無類型語言（untyped），換句話說，在語言層面上，Perl和大多數程式語言不同，不把變量分成整數、字符、浮點數等等，而只有一種能接受各種類型數據的「無類型」變量。Perl的變量以$字符開頭。例如`$a=5;``$b="Hello";``$c=3.2;``$d='\n这里并不换行';`都是合法的Perl語句。

Perl中各種變量的運算也很自由，數和含有數的字串是等效的，可以把數字字串參與數學計算，也可以反之，讓數字參與字串的構成和操作。

除單個變量（Perl稱為標量「Scalar」）之外，Perl還有兩種集合類型，分別是陣列（Array，用@字符開頭）和關聯數組（Associative array，或者稱為Hash，用%開頭。類似C++11的STL 無序表「unordered_map」和Python的字典「Dictionary」）。陣列可以內含任意可變數目的變量，並以其存儲順序作為索引以完成常數時間的定位；而Hash表，則可以在變量之間建立一一映射，就像字典一樣，把不同的變量按照他們的邏輯關係組織起來，並以作為「鍵」的變量進行索引，完成常數時間的定位。

另外，Perl還有一種特殊的類型，引用（reference），類似於指針，當作標量處理，可以指向標量（含引用）、陣列、Hash等任何類型。如：

```perl
$foo = \$bar; print $ $foo;
$foo = \@bar; print @$foo;
$foo = \%bar; print %$foo;
$foo = \&bar; print $foo->();
```

引用的好處在於，將它傳遞給函數之後，函數可以修改它指向的變量。而如果傳遞普通變量，修改的值只在函數內有效。

```perl
sub foo
{
    my $var = shift;
    $$var = '1';
}
my $foo = '2';
my $var = \$foo;
print $$var;
foo ($var);
print $foo;
```

輸出「21」，即foo內改變了$foo。

### 判斷語句

因為Perl大量的創造冗餘的語法，並且從其他語言中大量的借鑑語法，使得Perl的語法極其豐富和靈活。Perl共有下列幾種判斷語句：

- if區塊

```perl
if ($hour > 22) {
    print "should sleep...\n";
}
```

- if語句

```perl
print "hello" if $guest >= 1;
```

- unless區塊

```perl
unless ($credit > 100) {
    print "You can not graduate!\n";
}
```

- unless語句

```perl
print "eat\n" unless $food == 0;
```

- given/when(語句及區塊)

```perl
use 5.010;
given ($foo)
{
    say 'a' when 'a';
    when (/b/) { say 'b'; } #when可以写成语句或区块
    default { say 'not match'; } #只可以写成区块。
}
```

由於邏輯運算元的作用，還可以寫出不用關鍵字if或unless的判斷語句，如常用的打開文件語句：

```perl
open DATA, '<', $filename or die "Can't open $filename: $!\n";
```

### 循環語句

Perl中的循環語句也是非常的豐富。主要有：

Perl自己的for或者foreach循環(兩個完全一樣)：

```perl
@group = 1 .. 10;
for (@group) {
    print "$_\n";
}
print "$_\n" for @group;
foreach (@group) {
    print "$_\n";
}
```

從C語言借鑑來的for循環(又可寫作foreach，兩個完全一樣)：

```perl
for ($i = 0; $i < 10; $i++) {
    print "$group[$i]\n";
}
```

while循環：

```perl
$i=0;
while ($i < 10) {
    print "$group[$i]\n";
    $i++;
}
```

do...while循環：

```perl
$i = 0;
do {
    print "$group[$i]\n";
    $i++;
} while ($i < 10);
```

until循環：

```perl
$i = 0;
until ($i == 10) {
    print "$group[$i]\n";
    $i++;
}
```

從PASCAL語言借鑑來的do...until循環：

```perl
$i = 0;
do {
    print "$group[$i]\n";
    $i++;
} until ($i == 10);
```

甚至還有利用動態語言特性，用map函數做循環：

```perl
map { print "$_\n" } @group; #每行打印group里的一个元素
```

其實還有其他的循環方式。總而言之，就是TMTOWTDI。

## Perl的應用

Perl使用非常廣泛。在Unix、GNU/Linux和macOS中，Perl是內置的系統腳本工具。Perl曾經在網頁中（PHP，CGI）廣泛使用。Perl擁有海量的模塊支持，在解決問題時，可以直接安裝使用，非常方便。截止2025年2月2日，CPAN上發布了大約266,924個Perl模塊。

### 以Perl編寫的軟體

- Bugzilla
- Movable Type
- TWiki
- Frozen Bubble

### Perl Data Language

Perl Data Language（簡稱PDL）是Perl的一個外接模塊，也是對Perl功能的一個重要拓展。它使得Perl語言可以直接對2至多維的矩陣直接操作，進行快速的矩陣運算，完成基礎的Perl所不能完成的運算，大大拓展了Perl的適用範圍。所以PDL本身也是很多其他模塊的基礎。

而且PDL提供了與很多其他軟體包的接口，例如FFTW（一個快速傅立葉變換的軟體包），又或者是Mesa（Linux上的OpenGL三維圖形渲染包），這些包原來往往僅提供C/C++語言接口。這一功能使PDL成為拓展Perl功能的一個中間層。

## Perl的社區文化

### Perl詩經

和C語言一樣，在Perl界，難以讀懂的程式碼大賽是個有名的活動。近似難以讀懂的程式碼，但方向不同，Perl Poetry是可以被perl編譯的詩。新的詩經通常會在 網站發表。

### JAPH

Just another Perl hacker（另一個Perl黑客）是一個和國際C語言混亂代碼大賽有著相同精神的社區文化。Perl程式設計師通過寫JAPH代碼，來分享自己的編程技術。

## 競爭對手

因為許多Perl程序的代碼難以閱讀，加上它的面向對象功能被視為不是真正的面向對象(只是模組的模擬)，於是很多人拿Perl和其他動態語言來比較。

最常見的比較對象是Python，有人寫了篇文章叫《What's wrong with Perl》，指出Perl的缺點，鼓勵別人學Python。著名黑客埃里克·史蒂芬·雷蒙寫了《Why Python?》，該文中一個重要的比較對象就是Perl。《A Byte Of Python》裡的《Why Not Perl?》也把Python和Perl比較。

Ruby的作者（松本行弘，Matz）甚至承認他想讓Ruby作為Perl的後繼者。

## Raku（舊名Perl 6）

<image>

2000年開始，拉里·沃爾著手開發Perl 6來作為Perl的後繼，2019年更名為Raku。

在Perl的官網介紹中，Raku不是Perl 5的下一個版本，而是與Perl 5並行開發的另一種程式語言。

Raku更好地支持面向對象，有專用於定義類的語法：

```perl
class Foo is Universal { # inherit form Universal
    has $.member_variable

    method member_function {
        print "some string";
    }
}
```

Raku可以明確定義變量類型，當類型不匹配，編譯時報錯。

另外，Raku提供了不同的正則表達式語法，新的語法稱作「規則」，並且允許使用者在正則表達式中加入空格等以便閱讀，還可以命名一個正則表達式方便調用。

Raku中的控制流程和循環的判斷條件的括號可選:

```perl
if $percent > 100  {
    say "weird mathematics";
}
for 1..3 {
    # using $_ as loop variable
    say 2 * $_;
}
for 1..3 -> $x {
    # with explicit loop variable
    say 2 * $x;
}
while $stuff.is_wrong {
    $stuff.try_to_make_right;
}
```

但是如果加入括號，不能緊跟在關鍵字後面，而要空一格，因為用foo這樣的形式，編譯器識別為調用函數foo，而不管它是不是關鍵字：

```perl
if ($hour > 22) { #正確
    say 'should sleep...';
}
if($hour > 22) { #錯誤
    say 'should sleep...';
}
```

## 外部連結

- Perl.com （O'REILLY）
- Perl.org
- Perl 6的開發網頁
- CPAN - Comprehensive Perl Archive Network：Perl程式的集中地
- CPAN檢索
- dmoz on Perl
- Perl Mongers：全球各地的使用者組織
- Perl Monks：一個很活躍的Perl社區
- ActiveState：Microsoft Windows上的Perl
- Strawberry Perl：由Perl社群所提供之Microsoft Windows版Perl
- Perl6::Perl5::Differences

## 基本資料

- 編程范型：多重編程範式：函數、指令式、面向對象 (類別為基)、反射、過程式、事件驅動、泛型
- 設計者：拉里·沃爾
- 開發者：拉里·沃爾
- 類型系統：動態
- 施影響於：CoffeeScript、ECMAScript、Groovy、JavaScript、Julia、LPC、Perl 6、PHP、Python、Ruby、Windows PowerShell
- 許可證：藝術許可協 1.0、GNU通用公共許可證
- wikibooks：Perl Programming
- 發行時間：1987年12月18日
- 軟體版本週期：5.36.0 / 2022年5月28日 5.34.1 / 2022年3月13日
- 預覽版本：5.37.0
- 預覽版本：2022年5月28日
- turing-complete：Yes
- 受影響於：AWK、C語言、C++、Lisp、Pascal, sed、Smalltalk 80、Unix shell
- 實作語言：C語言
- 作業系統：跨平台
- 文件擴展名：.pl, .pm, .t, .pod