先前的章節或多或少已經介紹過輸入與輸出 (input/output 常簡寫為IO) 的一些用法. 現在就讓我們先將 "標準輸入" 當成 "鍵盤" 以及將 "標準輸出" 當作 "螢幕"吧.
讀取標準輸入 :
讀取標準輸入串流相當容易 ; 我們在前面已經用過
- $line =
; # 讀取下一列 - chomp($line); #然後把尾端的換行符截掉
- while(defined($line =
)) { - print " I see: $line";
- }
- while(
) { - print " I see: $_";
- }
- foreach(
) { - print "I see $_"; # 會等使用者在輸入檔案結束符後, 將回傳的串列一行行輸出.
- }
從鑽石運算符輸入 :
程式的調用引數 (invocation argument) 通常是命令列上跟在程式名稱之後的幾個 "單字". 在下面例子裡, 命令列引數代表要依序處理的幾個檔案名稱 :
$ ./my_program john ken peter
這道命令的意思是, 執行 my_program 命令, 然後該命令應該處理檔案 john, ken 最後是檔案 peter. 若是不提供任何調用引數, 則該程式應該從標準輸入串流處理. 但有個特例 ; 如果某個引數是連字符 (-) , 那也代表標準輸入. 所以假如引數是 "john - ken" 的話, 代表式應用程式先處理 john, 接著是標準輸入最後才是 ken. 既然鑽石運算符可以從標準輸入讀取, 所以上面的範例是可以寫成 :
- while(<>) {
- chomp;
- print "I see $_\n";
- }
調用引數 :
嚴格來說鑽石運算符並不會真的去檢查調用引數 ; 它靠的是 @ARGV 陣列. 這個陣列是先由 Perl 解譯器建立的特殊矩陣, 其內容就是調用引數所組成的串列. 而 @ARGV 的用法於其他陣列相同 ; 你可以把元素從它裡面 shift/pop 出去, 或是用 foreach 逐項加以處理. 你也可以檢查是否有引數是以連字號 (-) 開頭的, 然後將它們當成調用逐項處理. 因此你可以在使用鑽石運算符前, 對這個陣列進行加工以得到你要的結果.
用printf 來編排輸出結果 :
處理輸出結果時, 也許你會希望使用控制能力比 print 更強的函式. 事實上你可能已經習慣 C 的 printf 函式, 來產生編排過的輸出結果. 而Perl 裡有同名的函式提供類似的功能.
printf 函式的引數包括 "格式字串" 即 "所要印出的資料串列" 格式. 格式字串式填空用的模板, 代表你要輸出的格式 :
printf "Hi, %s : Your code will be ineffective after %d days!\n", $user, $days_to_die;
而有關 printf 的相關使用說明, 你可以參考 這裡.
一般來說你不會將陣列當成 printf 的引數. 這是因為陣列可以包含任意數目的元素, 而格式字串只會用到固定數目的元素 : 假如格式字串有三個轉換格式, 那就必須要有剛好三個元素可供使用. 不過沒有人規定你不准在程式執行時產生格式字串 ; 它們可以是任意的運算式. 想要把事做好, 需要一點技巧, 看來先把格式字串存進變數可能是不錯的建議 (尤其在除錯時):
- my @items = qw(john peter ken);
- my $format = "Item list: \n" . ("%10s\n" x @items);
- printf ($format, @items);
檔案代號 :
Perl 提供三種預設檔案代號 - STDIN, STDOUT 與 STDERR -- 都是產生 Perl process 時自動開啟的檔案或裝置. 當你需要其他檔案代號時, 可以使用 open (Opens a file using the specified file handle) 函式告訴 Perl, 要求作業系統為你程式開取與外接溝通的橋梁. 參考範例如下 :
- open CONFIG, "john";
- open CONFIG, "
; - open FHANDLE, ">ken";
- open LOG, ">>logfile";
而第三個例子, 它會開啟檔案代號 FHANDLE 並輸出內容到新檔案 ken. 如果檔案已經存在則會清除原有檔案的內容.
第四個例子, 說明你可以使用 ">>" 符號指名以附加方式開啟檔案. 換句話說如果檔案原本就存在, 那麼新的資料將會被附加到原有檔案內容之後 ; 如果檔案不存在, 就會建立一個新的檔案. 而在指名檔案名稱地方, 你可以使用任何的純量表示法 :
- my $file_name = "john";
- open HANDLE, "> $file_name"; 開啟檔案 john 進行覆蓋寫入動作
- my $success = open LOG, ">>logfile";
- unless($success) {
- print "Open fail!\n";
- } else {
- print "Open success!\n";
- }
- close LOG;
close HANDLE;
所謂關閉檔案代號就是在告訴作業系統, 我們對該資料串流的處理已經全部完成, 所以請系統將尚未寫入磁碟的輸出寫到磁碟, 以免有人等著使用它. 如果你開啟某個檔案代號或是結束程式, Perl 會自動關閉原先的檔案代號.
使用 die 來處理嚴重錯誤 :
當 Perl 發生嚴重錯誤時, 你的程式應該要中止執行, 並列印錯誤訊息已告知原因. 這樣的功能我們可以用現成的 die 函式來達成, 它讓我們能夠自製 "嚴重錯誤訊息".
die 函式會印出你所指定的訊息, 並且讓你的程式在非零的結束狀態立刻終止. 每個在 Unix 上執行的程式, 都會有一個結束狀態 (exit status), 用來告訴我們程式執行結果是否成功. 以執行其他程式為本務的程式 (像是工具程式 make), 會檢視那些程式的結束狀態, 來判斷是否一切順利. 所謂的結束狀態其實也只能以一個位元組來表示, 所以它能傳遞的訊息不多 ; 傳統上, 零代表成功, 非零代表失敗. 所以我們可以將前面的例子改寫成 :
- if(!open LOG, ">>logfile") {
- die "Can't not open logfile: $!";
- }
- close LOG;
除此之外 die 還會幫你做一件事, 它會自動將 Perl 程式名稱和列號附加在錯誤訊息的後面, 因此你就容易對源代碼進行除錯, 如果你不想要顯示列號於檔案名稱, 請在 die 函式訊息尾端加上換列字符, 就可以取消這樣的功能 :
- if(!open LOG, ">>logfile") {
- die "Can't not open logfile: $!\n"; # 加上 "\n" 表示不顯示列號與檔案名稱.
- }
使用檔案代號 :
當檔案代號以讀取模式開啟後, 你可以輕易的從它讀取一列資料, 就像從 STDIN 標準輸入串流讀取一樣, 參考範例如下 :
- my $file_name = "test.txt";
- if(!open TEST, $file_name) {
- die "Fail to open $file_name ($!)";
- }
- while(
) { - chomp;
- print "I See > $_\n";
- }
- close TEST;
- print LOG "Output to logfile...\n"; # 輸出到 LOG
- printf STDERR ("Already completed %d.\n", $done/$total * 100);
將資料輸出到檔案代號預設上都會經過緩衝, 不過只要將特殊變數 $| 設為 1, 就會立刻出清資料. 所以如果要讓輸出的內容立即送到檔案便可以這麼做.
沒有留言:
張貼留言