給perl 5.10初學者的介紹
作者:chromatic , Doug Sheppard
翻譯:WWW.17LAMP.NET JianXin.
繁體轉換工具:網頁線上轉碼
校正:ㄚ琪
首先,一個小小的促銷
作者的注釋:這個系列是基于Doug Sheppard的 Beginner’s Introduction to Perl的, A Beginner’s Introduction to Files and Strings with Perl 5.10解釋如何使用檔案和字串,A Beginner’s Introduction to Regular Expressions with Perl 5.10探究正規表示式、比對及取代, A Beginner’s Introduction to Perl Web Programming 說明如何寫web程式。
歡迎來到Perl。
Perl 是Swiss Army 程式設計語言的一部分:功能強大並且很容易學習。它首先是被Larry Wall 開發的。一位在1980年代末在NASA任系統管理員的語言學家,作為一種使得報告工作更加容易的方法。自那以後,它已經進入很多不同的領域:自動管理系統,作為不同電腦系統之間的連結、網路程式、生物資訊、資料整理,甚至應用程式的開發。
為什麼Perl會變得如此的流行當網絡隨之而來之時?有兩個原因:首先,大部份在網路上所作的事是關於文字的,而這最好是用一個專門設計用來處理文字的語言來處理。更重要的是,當人們需要使用一些東西時Perl比其他的選擇更加好。C語言很複雜並且可能產生安全問題(尤其是有不可信任的資料時),Tcl很難用,Python沒有一個真正的立足點。
Perl是一種友好的語言。它與你的個人的程式設計風格能夠很好的配合。Perl的口號是“有一種以上的方法來作一件事。”那使得它可以同時解決大的和小的問題。更多的是,Perl是可移植的並且普遍的--它幾乎可以在任何機器上預先安裝--當然在CPAN還有很多自由發行的函式庫。
這是我們的系列的第一部分,你將會學習一些有關Perl的基礎知識並會看到一個小的範例程式。
關於作業系統的一些話
這個系列假設你正在使用一個Unix或者Unix-like操作系統( Mac OS X 和 適合使用Cygwin)並且在/usr/bin/perl你有一個可用的Perl函式庫。如果你在Windows使用ActivePerl 或者 Strawberry Perl那也是可以的;大多數的Perl的程式碼是與平台無關的。
第一個Perl程式
把這個文件存為first.pl:
use feature ‘:5.10’;
say “Hi there!”;
(傳統的第一個程式:對世界說Hello!但是我是一個傳統叛逆者。)
執行這個程式。在命令列,進入文件的所在目錄並且輸入:perl first.pl。你應該看到:
Hi there!
很友好,不是嗎?
我敢保證你會猜測程式是什麼意思。use feature ‘:5.10’;一行是什麼?現在,你所需要知道的是它允許你好好地使用在Perl 5.10中的新特性。這是件非常好的事。
函數和陳述
Perl有很豐富的內建函數的函式庫。它們是Perl的動詞,是解譯器執行的命令。你可以在perlfunc的man手冊(在命令列中輸入 perldoc perlfunc)中看到一個內建函數的列表。幾乎所有的函數都會有一個有逗號隔開的參數列表。
print函數是Perl最常使用的一部分。你用它來在螢幕上顯示東西或者發送消息到一個文件。它使用一個事物的列表作為它的參數。
print “This is a single statement.”;
print “Look, “, “a “, “list!”;
一個Perl程式包含敘述,每個敘述都以一個分號結束。敘述不需要在分開的行;可能在一行中有很多的敘述。你也可以分開單一的一個敘述在不同的行。
print “This is “; print “two statements.n”;
print “But this “, “is only one statement.n”;
但是等一下。say和print之間的區別是什麼呢?在print敘述中的n是什麼?
say函數就像print函數,除了它會添加一個跳行在參數的末端之外。它會輸出所有的參數和一個跳行字元。其它就沒什麼區別了。print,另一方面,只是輸出在這些例子中你確實看到的。如果你想要跳行,你必須增加一個特殊字元n。
use feature ‘:5.10’;
say “This is a single statement.”;
say “Look, “, “a “, “list!”;
為什麼它們都會存在呢?為什麼你會使用它們兩個?通常,大多數“顯示一些東西“敘述需要跳行。say通常就足夠了,它是一個很好的預設選擇。偶爾你需要對你的輸出有少許的控制,所以print就可以選擇。
記住say比print少兩個字元。這是perl一個重要的設計原則--常見的事情應該是容易和簡單的。
數字、字串和引號
在Perl中有兩個基本的資料類型:數字和字串。
數字很簡單;我們已經處理過了它們。你僅僅需要做得是你需要知道在Perl中,你不可以在數字中輸入逗號或者空格。可以寫10000,但不可以寫10,000或者10 000。
字串會有些複雜。一個字串是一個在單引號或者雙引號中的字元的集合:
‘This is a test.’
“Hi there!n”
單引號和雙引號之間的區別是單引號意味著它們的內容被認為是逐字的字串,而雙引號則意味其內容可以被解譯的。
記得字元n嗎?它代表一個跳行當它出現在一個雙引號的字串中時,但是如果是在單引號的字串中那就只是逐字解譯成一個斜線及一個n的字元。
use feature ‘:5.10’;
say “This stringnshows up on two lines.”;
say ‘This string n shows up on only one.’;
(另外兩個有用的斜線字元是t用來插入一個tab字元,用來插入一個斜線到一個雙引號中的串。)
變數
如果說函數是Perl的動詞,那麼變數就是名詞。Perl有三種類型的變數:純量、陣列和雜湊。分別把它們看成事物、列表和字典。在Perl中,所有可用的名字包含一個標點符號、一個字母或者底線,一個或者多個混合符號的字母或者底線。
純量是一個單一的事物。這可能是一個數字或者一個字串。純量的名字用一個美元符號開始,比如$i或者$abacus。指定一個值給一個純量告訴Perl它等於什麼:
my $i= 5;
my $pie_flavor= ‘apple’;
my $constitution1776 = “We the People, etc.”;
你不需要特別指出一個純量是一個數字還是一個字串。這並不重要,因為Perl需要以字串的方式處理一個純量,它就會這樣去做;它需要把它當作數字,它也會這麼做。這種對話會自動發生。(這是與其它的語言不同的地方,在其它語言中字串和數字是兩種分開的資料類型。)
如果你使用一個雙引號的字串,Perl將會插入任何在字串中你命名的純量變數的值。直接填充一個字串時很有用:
use feature ‘:5.10’;
my $apple_count= 5;
my $count_report = “There are $apple_count apples.”;
say “The report is: $count_report”;
這個程式碼的最後的輸出是:he report is: There are 5 apples..
你在Perl中可以控制數字來作一般的數學運算:加法,乘法,除法和減法。(順便說一下,在Perl中乘法和除法的運算元使用*和/。)
my $a = 5;
my $b = $a + 10;# $b is now equal to 15.
my $c = $b * 10;# $c is now equal to 150.
$a= $a – 1;# $a is now 4, and algebra teachers are cringing.
這些都是很好的,但是奇怪的是my是什麼呢?為什麼有些有有些沒有?這個運算元告訴Perl你宣告了一個新的變數。也就是說,你向Perl保證在你的程式中你想要使用一個特別的純量、陣列或者雜湊。這很重要,有兩個原因。首先,它幫助Perl幫助你保護輸入的內容;那會是很尷尬的當你發現你突然打錯了一個變數名字,花費了一個小時來找到這個漏洞。第二,它幫助你寫更大的程式,這裡被使用在程式碼的一部分的變數不會影響到其他地方使用的變數。
你也可以使用特別的運算元,比如說++,–,+=,-=,/=和*=。它們在一個等式中操作一個純量的值而不用兩個元素。一些人喜歡它們,另一些卻不是。我喜歡這個事實它們會使得程式碼更簡潔。
my $a = 5;
$a++;# $a is now 6; we added 1 to it.
$a += 10;# Now it’s 16; we added 10.
$a /= 2;# And divided it by 2, so it’s 8.
在Perl中的字符串沒有這樣的自由性。僅有的基礎的你可以在字符串中使用運算符是連接運算符,這是一種“放在一起”的說法。這個連接運算符就是句號。連接和加法運算符是兩個不同的事物:
my $a = “8”;# Note the quotes.$a is a string.
my $b = $a + “1”;# “1” is a string too.
my $c = $a . “1”;# But $b and $c have different values!
記住Perl會在任何必要的時候自動的轉化字串為數字,所以要得到$b的值,Perl解譯器會把兩個字串“8”和“1”轉化為數字,然後將它們相加。$b的值變為數字9。然而,$c使用連接運算元,它的值會是字串“81”。
記住,加號用來操作數字而點號用來將字串連在一起。如果你對不是數字的事物做加法運算,Perl會盡最大努力來完成你讓它去做的工作,並且轉換那些不是數字的事物為數字。
陣列是一個純量的列表。陣列名用@開始。你通過在括號中列出它們的內容來定義一個陣列,元素用逗號隔開:
my @lotto_numbers = (1, 2, 3, 4, 5, 6);# Hey, it could happen.
my @months= (“July”, “August”, “September”);
你用索引來跟蹤一個陣列,比如“Hey, give me the first month of the year.”。在Perl中索引從零開始。(為什麼不是1?因為,這是計算機的事情。)要跟蹤一個陣列的元素,你需要把@替換成$,緊接著是你想要的元素的索引位置(它以一個美元符號開頭因為你正在獲得一個純量值。)你也可以就地修改它,就像任何其他的純量。
use feature ‘:5.10’;
my @months = (“July”, “August”, “September”);
say $months[0];# This prints “July”.
$months[2] = “Smarch”;# We just renamed September!
如果一個陣列值不存在,Perl會當你給它賦值時為你建立它。
my @winter_months = (“December”, “January”);
$winter_months[2] = “February”;
陣列總會以同樣的順序返回它們的內容;如果你遍歷@month,無論你做多少次,你總會以July, August, September 的順序得到它們。如果你想要找出陣列的元素個數,把這個陣列賦值給一個純量。
use feature ‘:5.10’;
my @months= (“July”, “August”, “September”);
my $month_count = @months;
say $month_count;# This prints 3.
my @autumn_months; # no elements
my $autumn_count = @autumn_months;
say $autumn_count; # this prints 0
一些程式語言把雜湊叫做“字典”。那就是因為:一個字和一個定義。更準確的說,它們包含鍵和值。每個在雜湊中的鍵都僅有的一個相對應的值。雜湊的名稱以一個百分號開始,你用逗號隔開的鍵和值來定義雜湊,就像這樣:
my %days_in_month = ( “July” => 31, “August” => 31, “September” => 30 );
你可以得到任何雜湊中的值通過 $hashname{key},或者就地修改它就像其他的純量。
say $days_in_month{September}; # 30, of course.
$days_in_month{February} = 29; # It’s a leap year.
要查看一個雜湊中的鍵,使用keys函數和雜湊的名字。這個函數傳回一個包含所有雜湊鍵的一個陣列。這個陣列不會總是相同的順序;而你可以相信@month總是以同樣的順序傳回 July, August, September, keys %days_in_summer可能會以任何順序傳回它們。
my @month_list = keys %days_in_summer;
# @month_list is now (‘July’, ‘September’, ‘August’)!
這三種類型的變數有三個不同的命名空間。那就意味著$abacus和@abacus是兩個不同的變數,並且$abacus[0](@abacus的第一個元素)與$abacus{0}(鍵值為0的%abacus的值)是不同的。
註解
一些前面部分的程式碼的例子包含程式碼註解。這對于解釋一個特別的程式碼片段是很有用的,並且對於任何一個你想要修改,改進,修理或者只是看一看的程式碼片段也是很重要的。(也就是說,註解很重要。)
任何一行Perl程式碼跟隨一個#作為註解,除非#出現在一個字串中。
use feature ‘:5.10’;
say “Hello world!”;# That’s more like it.
# This entire line is a comment.
迴圈
幾乎每一種程式都會使用迴圈。迴圈允許你重複執行同一個程式碼片段。這是程式設計中一般觀念的一部分叫做流程控制。
Perl有一些不同而有用的流程控制函數,最基礎的是for。當你使用for函數時,你指定一個變數用作迴圈索引,一個列表的值用來作為迴圈的內容。在一對大括號之間,你可以寫你想要迴圈完成的程式碼:
use feature ‘:5.10’;
for my $i (1, 2, 3, 4, 5) {
say $i;
}
這個迴圈輸出1到5的數字,每行輸出一個。(這不是很有用;你可能想“為什麼不寫say1,2,3,4,5;?”這是因為say只會跳一行,在它的參數列表的末端。)
有一個方便捷徑可以定義迴圈值叫做範圍 運算元 ..,用來指定一個範圍的數字,你可以寫(1, 2, 3, 4, 5) 成為(1 .. 5),你也可以在你的迴圈列表使用陣列及純量,試試程式碼並看看發生什麼事:
use feature ‘:5.10’;
my @one_to_ten = (1 .. 10);
my $top_limit= 25;
for my $i (@one_to_ten, 15, 20 .. $top_limit) {
say $i;
}
當然,你又一次可以寫say @one_to_ten, 15, 20 .. $top_limit;
在你的循環列表中的事物不一定是數字;你可以方便的使用字符串。如果散列%month_has包含月份名稱和每個月的天數,你可以使用keys函數來便利它們:
use feature ‘:5.10’;
for my $i (keys %month_has) {
say “$i has $month_has{$i} days.”;
}
for my $marx (‘Groucho’, ‘Harpo’, ‘Zeppo’, ‘Karl’) {
say “$marx is my favorite Marx brother.”;
}
複利的奇蹟
關於Perl你現在已經知道足夠多了--變數、print/say和for()--來寫一個小的、有用的程式。每一個人都喜歡錢,所以第一個例子是一個複利計算器。它將會輸出一個格式工整的表格顯示一個在投資幾年之後的值(你可以在 compound_interest.pl中看到程式)
程式中最複雜的的一行是:
my $interest = int( ( $apr / 100 ) * $nest_egg * 100 ) / 100;
$apr / 100 是利率,($apr / 100) * $nest_egg 是一年之內的利息。這一行使用了int()函數,它會返回一個整數的純量值(它的值省略掉所有的小數部分)。我們在這裡使用int()是因為如果你相乘,比如說,10925乘以9.25%,結果是 1010.5625,我們必須捨入到1010.56。要做這些,我們要乘以100,得到 101056.25,使用int()來扔掉多餘的小數部分,得到101056,然後再被100除,最後的結果是1010.56。試著自己跟著這個程式碼來看看我們是怎樣得到最後的正確答案。
玩一玩!
現在你有了一些基本的Perl語法的知識並且一些簡單的玩具。試著用它們寫一些簡單的程式。這裡有兩點建議,一個很簡單,另一個有一些複雜:
- 一個字頻計數器。在一個陣列中,一個字出現的頻率是多少?輸出結果(提示:用一個雜湊來記錄每個文字出現的次數)
- 給出一個月和一個星期的天數作為這個月的第一天,輸出一個這個月的日曆。