Perl命令行應用介紹

作 者: Dave Cross
發 表:August 10, 2004
原 名: Perl Command-Line Options
原 文:[color=blue]http://www.perl.com/pub/a/2004/08/09/commandline.html[/color]
譯 者: "Qiang":qiang

Perl 有很多命令行參數. 通過它, 我們有機會寫出更簡單的程序. 在這篇文章裏我們來了解一些常用的參數.

Safety Net Options

在使用 Perl 嘗試一些聰明( 或 stupid) 的想法時, 錯誤難免會發生. 有經驗的 Perl 程序員常常使用三個參數來提前找到錯誤所在, 

-C 是第一個. 這個參數編譯 Perl 程序但不會真正運行它. 由此檢查所有語法錯誤. 每次修改 perl 程序之後我都會立刻使用它來找到任何語法錯誤.

   
$ perl -c program.pl


-W 是第二個參數. 它會提示你任何潛在的問題. Perl 5.6.0 之後的版本已經用 use warnings; 替換了 -w .你應該使用 use warnings 因爲它要比 -w 更靈活.

-T 是第三個參數. 它把 perl 放到了 tain 模式.  在這個模式裏, Perl 會質疑任何程序外傳來的數據. 例如,從命令行讀取, 外部文件裏讀取 或是 CGI 程序裏傳來的數據. 這些數據在 -T 模式裏都會被 Tainted 掉.

Tainted 數據不可以被用來和外部交互. 例如 使用在 system 調用和用作 open 的文件名. perlsec 文檔裏有更多什麼數據會被Tainted 掉的例子.

要 想使用 Tainted 的數據就需要 untaint這個數據. untaint 是通過正則表達式來實現.這裏我不會太多的講述 taint 模 式. 如果你要編寫的程序 (例如 CGI 程序) 需要從從用戶那裏接受不可知的輸入, 我推薦使有 taint 模式

-d ,Perl Debugger , 在這裏值得一提但我們無法顧及, 我推薦閱讀文檔 'perldoc perldebug' 或 Richard Foley 的
Perl Debugger Pocket Reference 一書.

Command-Line Programs

下面的幾個 Perl 參數可以讓短小的 Perl 程序運行在命令行. -e 可以讓 Perl 程序在命令行上運行.例如, 我們可以在命令行上運行 "Hello World" 程序而不用把它寫入文件再運行.

  
$ perl -e 'print "Hello World\n"'


多個 -e 也可以同時使用, 運行順序根據它出現的位置.

  
$ perl -e 'print "Hello ";' -e 'print "World\n"'

象所有的 Perl 程序一樣, 只有程序的最後一行不需要以 ; 結尾.

雖然你也可以象通常一樣引用模塊, 但 -M 讓它變得更容易.
  $ perl -MLWP::Simple -e 'print head "http://www.example.com"'


-M模塊名 和 use 模塊名 一樣. 如果不想引入模塊的缺省值, 你可以使用 -m. -m模塊名 和 use 模塊名() 一樣. 例如下面這個例子, 因爲 head 函數是缺省引入,而使用 -m 時就不會, 結果是沒有輸出.
  $ perl -mLWP::Simple -e 'print head "http://www.example.com"'


-m 和 -M 通過 = 來引入某個模塊的特別函數.

 
 $ perl -MCGI=:standard -e 'print header'


這裏, CGI.pm 的 ":standard" 被引入, header 函數因此可以使用.要引入多個參數可以通過使用引號和逗號.

  
$ perl -MCGI='header,start_html' -e 'print header, start_html'


這裏我們引入了 header 和 start_html 函數.

Implicit Loops

-n 和 -p 增加了循環的功能, 使你可以一行一行來處理文件.

 
 $ perl -n -e 'some code' file1


這與下面的程序一樣.

  
LINE:

    while (<>;) {

      # your code goes here

    }


<>; 打開命令行裏的文件,一行行的讀取.每一行缺省保存在 $_
  $ perl -n -e 'print "$. - $_"' file


上面的這一行可以寫成
  LINE:

    while (<>;) {

      print "$. - $_"

    }


輸出當前行數 $. 和當前行 $_.

-p 可以讓上面的程序變得更容易. -p 會輸出 $_ 就像這樣 

  
LINE:

    while (<>;) {

      # your code goes here

    } continue {

      print or die "-p destination: $!\n";

    }


continue 在這裏保證print 在每次循環都會被調用.

使用 -p, 我們的打印行數程序可以改爲
  $ perl -p -e '$_ = "$. - $_"'


注意到那個 LINE: 標籤 ? 我們可以利用它來跳到下一個循環. 使用 next LINE

  $ perl -n -e 'next LINE unless /pattern/; print $_'


如果想在循環的前後做些處理, 可以使用 BEGIN 或 END block. 下面的這一行計算文件裏的字數.
  $ perl -ne 'END { print $t } @w = /(\w+)/g; $t += @w' file.txt


每一行所有匹配的字放入數組 @w , 然後把 @w 的元素數目遞加到  $t. END block 裏的 print 最後輸出文件總字數.

還有兩個參數可以讓這個程序變得更簡單. -a 打開自動分離 (split)  模式. 空格是缺省的分離號. 輸入根據分離號被分離然後放入缺省數組 @F. 由此,我們可以把上面的程序改寫爲

  
$ perl -ane 'END {print $x} $x += @F' file.txt


你也可以通過 -F 把缺省的分離號改爲你想要的.例如把分離號定爲非字符:

  
$ perl -F'\W' -ane 'END {print $x} $x += @F' file.txt


下面通過 Unix password 文件來介紹一個複雜的例子.  Unix password 是文本文件, 每一行是一個 用戶記錄, 由冒號 : 分離. 第 7 行是用戶的登錄 shell 路徑. 我們可以得出每一個不同 shell 路徑被多少個用戶使用 :
  $ perl -F':' -ane '$s{$F[6]}++;' \

  >; -e 'END { print "$_ : $s{$_}" for keys %s }' /etc/passwd


雖然現在不是一行, 但是你可以看出使用參數可以解決什麼問題.

Record Separators

以 前我提到過 $/ 和 $\ -- 輸入,輸出分隔號. $/ 用來分隔從文件句柄裏讀出的數據, 缺省 $/ 分隔號是 \n , 這樣每次從文件句柄 裏就會一行行的讀取.  $\  缺省是空字符, 用來自動加到要 print 的數據尾端. 這就是爲什麼很多時候 print 都要在末尾加 上 \n. 

$/ 和 $\ 可與 -n -p 一起使用. 在命令行上相對應爲 -0 (零) 和 -l ( 這 是 L ). -0 後面可以跟一個 16 進制或8進制數值, 這個值用來付給 $/ . -00 打開段落模式, -0777 打開slurp 模式 (即可以一次把整個文件讀 入) , 這與把 $/ 設爲空字符和 undef 一樣效果.

單獨使用 -l  有兩個效果,  第一自動 chomp 輸入分隔號, 第二 把$/ 值付給 $\ ( 這樣 print 的時候就會自動在末尾加 \n )

我個人常常使用 -l 參數, 用來給每一個輸出加 \n. 例如

  
$ perl -le 'print "Hello World"'


[size=18]In-Place Editing[/size]

使用已有的參數我們可以寫出很有效的命令行程序. 常見的Unix I/O 重定向:

 
 $ perl -pe 'some code' < input.txt >; output.txt


這個程序從 input.txt 讀取數據, 然後做一些處理再輸出到 output.txt. 你當然也可以把輸出重定向到同一個文件裏.

上 面的程序可以通過 -i 參數做的更簡單些. -i  把源文件更名然後從這個更名的源文件裏讀取.最後把處理後的數據寫入源文件. 如果 -i 後跟有 其他字符串, 這個字符串與源文件名合成後來生成一個新的文件名. 此文件會被用來儲存原始文件以免被 -i  參數覆蓋. 

這個例子把所有 php 字符替換爲 perl :

  
$ perl -i -pe 's/\bPHP\b/Perl/g' file.txt


程序讀取文件的每一行, 然後替換字符, 處理後的數據重新寫入( 即覆蓋 ) 源文件. 如果不想覆蓋源文件, 可以使用

  
$perl -i.bak -pe 's/\bPHP\b/Perl/g' file.txt


這裏處理過的數據寫入 file.txt , file.txt.bak 是源文件的備份.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章