Perl 教學 -- 函數與字串處理
This tutorial is copyrighted and provided as is. You are welcomed to use it for non-commercial purpose.Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
請勿轉貼
看其他教材
函數 (Function):
- 建立與使用函數: 執行
- 這個範例用來說明如何宣告一個函數,並呼叫它。程式碼如下:
#!/usr/bin/perl sub Footer { print "<h2>Perl Program Using Functions</h2>\n"; print "\n</body>\n"; print "</html>\n"; } print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>\n"; print "<title>Perl Program Using Functions</title>\n"; print "</head>\n\n"; &Footer;
- 在程式碼中,我們宣告了一個名為 Footer 的函數(綠色的部分);函數宣告 的基本語法是使用保留字 sub 並在其後加上函數名稱(這個範例中使用的 是 Footer),函數名稱之後加上一對大括號,在大括號中加入必要的程式碼。
- 呼叫函數的語法是 &函數名稱,因此呼叫 Footer 的方式如程式碼 中紅色的部分。
- 這個範例用來說明如何宣告一個函數,並呼叫它。程式碼如下:
- 函數間傳送資料 (I): 執行
- 在前一個範例中,我們宣告了一個 Footer 的函數,但是該函數 並無法接收呼叫端傳送過來的參數,但是在大多數的程式中,能夠宣告一個能接受 參數的函數是必要的,這個範例就是用於說明該方式。
- 程式碼如下:
#!/usr/bin/perl sub Header { print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>\n"; print "<title>@_</title>\n"; print "</head>\n\n"; } sub Footer { print "<h2>Perl Program Using Functions</h2>\n"; print "\n</body>\n"; print "</html>\n"; } &Header("Perl Program Using Functions"); &Footer;
- 在程式中,我們把前一個範例中的 print 敘述全部定義在一個名為 Header 的函數(如綠色部分),然後呼叫它(如紅色部分)。請注意,呼叫端在函數名稱 之後加上了一對括號,並在括號內加入了一個字串,這代表呼叫 Header 並將 字串 "Perl Programming Using Functions" 傳給 Header;如果 Header 需要取用 該參數內容,則使用 @_。
- 嚴謹的說,@_ 代表一個呼叫端傳送過來的陣列。在本範例中,由於 只傳遞了一個參數,因此該陣列只有一個元素,我們也可以單獨使用 $_[0] 來取得該參數的內容,請試試看!
- 函數間傳送資料 (II): 執行
- 這個範例用於說明如何傳遞多個參數資料給函數,而且函數產生的結果 可以回傳給呼叫端。
- 程式碼如下:
#!/usr/bin/perl sub Root { my($a, $b, $c) = @_; my($tmp, $x1, $x2); $tmp = sqrt($b ** 2 - 4.0 * $a * $c); $x1 = (-$b + $tmp) / (2.0 * $a); $x2 = (-$b - $tmp) / (2.0 * $a); return ($x1, $x2); } $a = 1.0; $b = -2.0; $c = 1.0; @x = &Root($a, $b, $c); print "Content-type: text/html\n\n"; print "x1 = $x[0]; and x2 = $x[1]\n";
- 呼叫 Root 函數的時候,程式也傳遞三個參數資料(分別是變數 a、b、c; 這三個是全域變數),函數接收到資料後,將陣列資料 @_ 分別指定給 $a, $b, $c,其中,由於 ($a, $b, $c) 前面有 my, 因此這些變數 a、b、c 代表區域變數,而且只能在 Root 函數內使用;另外,Root 函數 又宣告了區域變數 tmp, x1, 和 x2。
- 等到 Root 函數計算出結果後,它以 return 將變數值 x1 和 x2 (嚴謹的說,將包含變數 x1 和 x2 的陣列)回傳給呼叫端。
- 呼叫端(紅色部分)將 Root 函數回傳的結果指定給一個名為 x 的陣列, 而其內容就可以 $x[0] 和 $x[1] 的方式將資料取出。
- 使用 require: 執行
- require 類似 C 語言的 include;基本上,它用來將另一個檔案的 內容"包"進檔案。
- 原始碼:
#!/usr/bin/perl require "req.pl"; &Header("Perl Program Using Functions"); &Footer;
- req.pl 的程式碼如下:
#!/usr/bin/perl sub Header { print "Content-type: text/html\n\n"; print "<html>\n"; print "<head>\n"; print "<title>@_</title>\n"; print "</head>\n\n"; } sub Footer { print "<h2>Perl Program Using Functions</h2>\n"; print "\n</body>\n"; print "</html>\n"; } return 1; # this is required.
日期函數
在撰寫 CGI-Perl 程式的時候,經常我們需要抓取系統的時間或日期。 Perl 提供了幾個有用的時間函數,你可以命令提示字元的視窗內下 perldoc perlfunc 的指令,然後搜尋 localtime 或 gmtime。 本範例我們介紹 localtime 的使用方式:#!/usr/bin/perl ($sec, $min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); print "秒: $sec\n"; print "分: $min\n"; print "時: $hour\n"; print "一個月的第幾天: $mday\n"; print "月: $mon 範圍是 0-11,而一月為 0\n"; print "距離 1900 年的第幾年: $year\n"; print "一周內的第幾天: $wday 範圍是 0-6,而星期日為 0\n"; print "一年內的第幾天: $yday\n"; # 如果我只想要當天的日期, ($_,$_,$_, $mday, $mon, $year, $_,$_,$_) = localtime(time); $year = $year + 1900; $mon = $mon + 1; print "今天是西元 $year 年 $mon 月 $mday 日\n";
字串、搜尋、與取代
- 例題 I:
#!/usr/local/bin/perl $url = 'www.nchu.edu.tw'; # Usage: /pattern/[g][o][i] # g for global, o for only once, and i for case-insentitive # url 是否包含 nchu 字串 if ( $url =~ /nchu/ ) { print "$url is 國立中興大學.\n"; } # 將 'edu' 取代為 EDU # Can you use tr? (ie. tr/edu/EDU/) $url =~ s/edu/EDU/; print "\$url is now $url.\n";
- 例題 II:
- 大寫變小寫
#!/usr/local/bin/perl $names = "fred and mary"; $names =~ tr/a-z/A-Z/; print "$names\n";
- 計算字串長度
#!/usr/local/bin/perl $count = "fred and mary"; # # 若不使用 =~, tr 傳回轉換的字元總數 $count = tr/a-z //; print "$count\n";
- 大寫變小寫
- 例題 III: 在使用 GET 方法的 Form 例題中, 請在輸入欄內輸入多於
一個字並觀察其執行情形。 你應該可以看到網址輸入欄內的內容 (如果輸入的是
aaa bbb)為 input=aaa+bbb。 這是因為空格被 "+" 符號 (URL-encoded characters)
取代。常見的 URL-encoded characters 包含:
Character URL-encoded characters Tab %09 空格 + ! %21 + %2B
那麼當成是接收到 input=aaa+bbb 的時候,它要如何將 + 轉換成空格呢?以下我們利用 GET 和 POST 的範例,分別列出轉換的方式。
- GET 的方式:
- form 表單:
- 該表單呼叫 sub.pl,而其程式碼如下:
#!/usr/local/bin/perl print "Content-type: text/plain\n\n"; $input = $ENV{'QUERY_STRING'}; # translate + into space. $input =~ tr/+/ /; print "$input.\n"; # s: substitute # \d: a number, A-F: A,B,C,D,E,F, a-f: a,b,c,d,e,f # [\dA-Fa-f]: either a number, A, B, ... , F, a, b, ..., or f. # pack("c", hex($1)): transform %[][] into a character ("c"). # e: treat pack() as an expression instead of a string. # $input =~ s/%(..)/pack("c", hex($1))/eg; $input =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack("c", hex($1))/eg; print "$input.\n";
- 程式碼中,除了第一段是進行之前說過的"將 + 轉換成空格",第二段我們 使用了更進階的方式將所有 URL-encoded characters 轉換成字串。為了容易說明, 請在表單中輸入一個中文字(例如空),執行後,讀者應該可以從網頁或者 瀏覽器的 URL 欄位看到,空(不含雙引號)這個字被轉換成的 URL-encoded characters 是 %AA%C5,這樣的內容程式必須加以處理才能轉換 成我們需要的空。轉換的規則如下:我們需要從資料內找出所有的 URL-encoded characters,而這些字元都符合 %XX 格式,而 X 代表 16 進位的數字(也就是 0-9A-F);Perl 的搜尋規則即為 %([\dA-Fa-f][\dA-Fa-f]);找到字元之後,我們利用 pack() 方法,將其 16 進位的資料轉換成字串。 pack() 的第一個參數 "c" 就是指定轉換成字串的設定,我們也可以 轉換成其他資料型態,有興趣的讀者,可以參考 pack 的用法。
- POST 的方式:
- form 表單:
- 該表單呼叫 subp.pl:因為該程式除了經由 POST 方式來讀取資料而跟 sub.pl 不同以外,其他部分相同,因此不再贅述。
- GET 的方式:
Written by: 國立中興大學資管系呂瑞麟 Eric Jui-Lin Lu
沒有留言:
張貼留言