與外界對話


Perl 本身已是一個相當強大的語言; 但是 perl 最大的力量來自於它與外界其他程式溝通的能力. 使用者本來就可以手動令你的 perl 程式與外界溝通, 例如想把目前目錄下所有檔案名稱的大小寫對調, 可以將 ls 的輸出餵給我們先前寫的 rencase 吃, 像這樣: ls | rencase 又如 count_arg 程式可以拿來數數看目前線上每個人 login 幾次, 像這樣: count_arg `who -q | grep -v '^#'` 但這需要使用我們程式的人懂得 pipeback quote 等觀念. 本單元要介紹的則是如何從你的 perl 程式 裡面 去執行外界的命令, 讓你的 perl 程式以四兩之力將千斤大問題撥給系統內其他程式去解決. 再收割成果呈現給使用者看, 讓不知情 (或不會自己下 pipe/back quote) 的使用者以為你有多厲害! (其實會發揮 組合的力量 的人, 真的很厲害.)

範例程式: 統計每位使用者上機次數與時間長短

四種基本方式

首先, 如果你只是想執行外部命令, 對這個外部命令產生的訊息並無興趣, 可以用 system 函數來執行外部命令:

        system("cp -r $ENV{HOME}/important $ENV{HOME}/backup");

當然, 你也可以用內建模組 File::Copy 做相同的事。

其次, 如果你不但要執行外部命令, 還希望在你的 perl 程式內分析它的結果, 那麼就用 back quote 來執行外部命令, 一口氣把它印出來的所有資料讀入一個陣列. 外部命令所印出來的每一列資料, 會依序存在陣列的每一個元素裡面:

        @x = `md5sum *.iso`;

但是上面的方法只適合用於資料量小, 或需要反複查詢的場合. 如果外部命令印出來的資料量太大, 全部讀入記憶體會很耗資源. 這時如果你的問題允許你循序每次只處理一列外部命令的輸出, 不需要經常回頭看過去的輸出, 那麼可以用第三種方法, 逐列處理:

        open F, "find $ENV{HOME} -name '*.*htm*' |";
        while (<F>) {
            ...
        }
        close F;

當然, 你也可以用內建模組 File::Find 做相同的事。

最後, 有時我們的 perl 程式所呼叫的外部命令是交談式的程式. 此時資料的流向顛倒過來, 變成是我們逐列送資料給外部程式. 還是用 open 的語法, 只不過 pipe 符號放的位置也顛倒過來:

        open F, "| gnuplot";
        print F "set term dumb\n";
        print F "plot sin(x)\n";
        close F;

Perl 語言

  1. 新手上路
  2. 基本要素
  3. 餵資料
  4. 常用句型
  5. regexp
  6. 詳談變數
  7. 一語中的
  8. 副程式
  9. 模組
  10. 外界對話

附錄

  1. 參考資料
  2. scripting
  3. Windows
  4. 圖形介面
  5. big-5 碼