FlossDoc: 請協力 GPLv3 的中文翻譯工作。
編寫 Perl 程式
FlossDoc,自由中文開源知識庫
如果您已認識其他程式語言 (programming language) 或腳本語言 (scripting language),這是一個非常簡短對 Perl 語法的介紹。
目录 |
Hello World 程式
以下是一個很簡單的 Perl 程式。
#!/usr/bin/perl print "Hello, world!"; # 這是注解
資料類別
Perl 和很多腳本語言一樣都屬 lossy type,並不強制分開數字、字串和物體等類型。您可以直接將字串中的數字作運算:
print "5.2" + "1.7"; # + 是數值運算 # 顯示 6.9
print "5.2" . "1.7"; # . 是字串運算 # 顯示 5.21.7
基本而言,Perl 的變數只分三類:
- 純量 (scalar) - 名稱以錢號 ($) 開頭,表示任何單一資料。例如:
$num = 6.9; $string = "Hello World!!"; - 陣列 (array) - 名稱以 @ 開頭,表示包括多個純量的串列。例如:
@odds = (1, 3, 5, 7, 9); - 散列 (hash, associate array) - 名稱以百分比號 (%) 開頭,
同樣,Perl 中的變數和很多 scripting 語言一樣無需要預先宣告 (declaration)。但如果開程式開啟加上 use strict; 敘述,可以令 Perl 要求每一個變數都要變 my $a, $b; 預先宣告,減少拼錯變數名稱的機會。
詳情可以參見 perldata(1)[1]
純量 ($scalar)
純量是 Perl 可以處理最簡單的類型,表示任何單一資料,包括數值 (numeric)、字串 (string) 和參考 (reference)。例如:
- 整數 (integer):
1,20,-280,031(八進位數,相等於 25),0xA31E(十六進位數,相等於 41758) 和0b101101(二進位數,相等於 45) - 浮點數 (float):
3.141573259,1.7E10,-2.56e15和10.0 - 字串 (string):
'哈囉! 世界!','12345678',"My name is $myname\n"
純量變數以錢號 ($) 開頭。
陣列 (@array)
陣列或串列 (list) 為一連純量組成 (0 個元素或以上) 組成的資料類型,例如:
(1, 2, 3) # 三個元素的串列
('John', "Mary", 2, 4, 'Peter') # 五個元素的串列
() # 空串列 (0 個元素的串列)
陣列變數以 @ 為開頭,可以使用 $var[$i] 存取第 $i - 1 個元表的值:
@names = ('John', 'Mary', 'Peter');
print $names[1]; # 顯示 Mary
$names[2] = 'David'; # @names 變成 ('John', 'Mary', 'David')
@nums = (2, 1, 6, 17);
@list = (@names, @nums); # @list 變成 ('John', 'Mary', 'David', 2, 1, 6, 17)
@words = qw(apple boy cat door); # @words 變成 ('apple', 'boy', 'cat', 'door')
print $#words; # 顯示 4 (@words 的元素數目)
foreach $word ( @words ) {
print "$word\n";
}
print pop(@words); # 顯示 'door', @words 變成 ('apple', 'boy', 'cat')
push(@words, 'ear'); # @words 變成 ('apple', 'boy', 'cat', 'ear')
print shift(@words); # 顯示 'apple', @words 變成 ('boy', 'cat', 'ear')
unshift(@words, 'zebra'); # @words 變成 ('zebra', 'boy', 'cat', 'ear')
注意事項:
- 取用陣列其中一個元素為純量,所以 $ 開頭。取用整個陣列則以 @ 開頭。
- 陣列變數和純量變數可以使用相同的名稱,但表示兩個獨立的變數。例如 $x 和 @x 是不同的變數。
散列 (%hash)
散列 (hash) 或叫作 associated arrays,和陣列很相似,但陣列用整數作索引,而散列則用字串作索引,稱為鍵 (key),對應的內容為值 (value)。散列變數以百分比號 (%) 作開頭,可以用 $var{$i} 存取鍵為 $i 的值:
%scores = {
'John Smith' => 88.2,
'Mary Doe' => 92.5,
'David' => 45.12
};
print $scores{'David'}; # 顯示 45.12
$scores{'peter'} = 'unknown';
print $scores{peter}; # 鍵的單引號可以省略
print "David has score\n" if exists $scores{'David'};
@names = keys(%scores); # @names 變成 ('John Smith', 'Mary Doe', 'David', 'peter')
@scores = values(%scores); # @scores 變成 (88.2, 92.5, 45.12, 'unknown')
while (($key, $value) = each %scores) {
print "$key => $value\n";
}
注意事項:
- 和陣列同理,取用散列其中一個鍵的值為純量,所以 $ 一樣以開頭。取用整個散列則以 % 開頭。
- 散列變數,陣列變數和純量變數可以使用相同的名稱,但表示三個獨立的變數。例如 $x,@x 和 %x 是三個不同的變數。
內建變數
以下只是列出幾個常用的內建變數,完整的列表請參看 perlvar(1)[2]
- $_ - 預設參數。任何函數沒有提供參數時會自動使用此變數作為函數,例如
print;等於print $_;,而/HKD\d+\.\d{2}/等於$_ =~ /HKD\d+\.\d{2}/。 - $0 - 現時執行程式的檔案路徑 (包括程式名稱)
- @ARGV - 現時執行程式的命令列參數
- @_ - 現時執行子程序的參數
- $$ - 現時執行程式的進程識別號 (PID)
- $. - 最後存取檔案標頭 (file handle) 的現時行號。
運算
值的真假:
- 0 為假,其他數值皆為真。
- '0', "0" 和空字串 、"" 為假,其他字串皆為真。
- 運算結果可以轉為 "0" 者為假,其餘皆為真。
- 未定義 undef 為假,有定意為真。
| 運算元 | 解析 | 例子 |
|---|---|---|
| -> | 呼叫方法/解參考 |
$a{'name'} = 'John Smith';
$obj = \$a;
print $obj->{'name'};
|
| ++ | 遞增 |
$i = 10 $i++; # 相等於 $i = $i + 1; $i 的值變成 11 print $i++ + 4; # 顯示 15, $i 的值變成 12 print ++$i + 4; # 顯示 18, $i 的值變成 13 |
| -- | 遞減 |
$i = 20 $i--; # 相等於 $i = $i - 1; $i 的值變成 19 print $i-- + 4; # 顯示 23, $i 的值變成 18 print --$i + 4; # 顯示 21, $i 的值變成 17 |
| ** | 乘幕 | print 2 ** 5; # 顯示 32 |
| ! | 非 | ! ($x == 0) # 相等於 $x != 0 |
| ~ | 位元運算非 | printf "%b\n", ~ 0b11010011; # 顯示 11111111111111111111111100101100 |
| \ | 參考 | |
| =~ | 比對 | $str =~ /match/ |
| !~ | 非比對 | $str !~ /nothing/ |
| * | 乘 | 4.2 * 12.7 # 結果為 53.34 |
| / | 除 | 24 / 9 # 結果為 2 |
| % | 餘數 | 123 % 12 # 結果為 3 |
| x | 重複字串 | print '+-' x 4; # 顯示 '+-+-+-+-' |
| + | 加 | 4 + 17 # 結果為 21 |
| - | 減 | 123.4 - 76.5 # 結果為 46.9 |
| . | 連接字串 | print 'John ' . 'Smith'; # 顯示 'John Smith' |
| << | 位元左移 | 0b1011 << 2 # 結果為 0b101100 |
| >> | 位元右移 | 0b1011 >> 1 # 結果為 0b101 |
| < | 小於 | |
| > | 大於 | |
| <= | 小於或等於 | |
| >= | 大於或等於 | |
| lt | 字串小於 | |
| gt | 字串大於 | |
| le | 字串小於或等於 | |
| ge | 字串大於或等於 | |
| == | 等於 | |
| != | 不等於 | |
| <=> | 數值比較 | |
| eq | 字串等於 | |
| ne | 字串不等於 | |
| comp | 字串比較 | |
| & | 位元 AND | |
| | | 位元 OR | |
| ^ | 位元 XOR | |
| && | 且 | |
| || | 或 | |
| .. | 範圍 | 2 .. 7 # 相等於 (2, 3, 4, 5, 6, 7) |
| ? : | 三元運算 | ($a > $b) ? $a : $b |
| = | 指定 | |
| += | 增加 | $n += $x # 相等於 $n = $n + $x |
| -= | 減小 | $n -= $x # 相等於 $n = $n - $x |
| *= | 乘上 | $n *= $x # 相等於 $n = $n * $x |
| , | ||
| => | ||
| not | 邏輯 NOT | |
| and | 邏輯 AND | |
| or | 邏輯 OR | |
| xor | 邏輯 XOR |
基本語法
每一個敘述 (statement) 一定以冒號 (;) 結束。
詳情可以參見 perlsyn(1)[3]
如果..則 (if..then)
最簡單的形式為:
if (算式) { 敘述... }
當然可以加上否則 (else) 的情況:
if (算式) { 敘述... } else { 敘述... }
否則如果 (else if) 則用 elsif:
if (算式) { 敘述... } elsif (算式) { 敘述... }... else { 敘述... }
還有 Perl 獨有的單行式:
敘述 if 算式;
別忘了 Perl 還有 unless 敘述,相等於 if (! 算式) ...:
unless (算式) { 敘述... } else { 敘述... }
或:
敘述 unless 算式;
例如:
if (!open(FOO)) {
die "Can't open $FOO: $!";
}
print "Basset hounds got long ears" if length $ear >= 10;
go_outside() and play() unless $is_raining;
open(FOO) or die "Can't open $FOO: $!"; # FOO or bust!
open(FOO) ? 'hi mom' : die "Can't open $FOO: $!";
# a bit exotic, that last one
注意事項:
- 是 elsif,不是 elseif,中間沒有 e 的。
while..do
while (算式) { 敘述... }
可以加上 continue 區塊 (每次完成 loop 都會執行 continue 區塊的敘述,包括 next 後):
while (算式) { 敘述... } continue { 敘述... }
單行式:
敘述 while 算式;
Perl 獨有的 until 等於 while (! 算式):
until (算式) { 敘述... }
或:
敘述 until 算式;
例如:
while (($key, $value) = each %hash) {
print "$key = $value\n";
}
$i = $j = 0;
print $i++ while $i <= 10;
print $j++ until $j > 10;
$i = 0;
while ($i < 10) {
print "$i\n";
} continue {
$i++;
}
# 以上相等於 for ($i = 0; $i < 10; $i++) { print "$i\n"; }
do..while
do { 敘述... } while 算式;
do { 敘述... } until 算式;
do {
$line = <STDIN>;
...
} until $line eq ".\n";
例如:
do {
$i++;
print "$i\n";
} while ( $i < 100 );
for loop
C 語言的 for 形式:
for (算式; 算式; 算式) { 敘述... }
亦有方便走訪所有陣列元素的 foreach 形式
foreach 變數 ( 陣列 ) { 敘述... }
或:
敘述 foreach 陣列;
for ($i = 1; $i < 10; $i++) {
...
}
print "Hello $_!\n" foreach qw(world Dolly nurse);
loop 控制
- last - 跳出 loop
- next - 跳至下一次 loop 或 continue 區塊
- redo - 重新執行這一次 loop
常用函數 (function)
這裡只列出較常用的內建函數 (function),完整列表可以參見 perlfunc(1)[4]
如果使用時沒有提無參數,一般預設使用變數 $_。
輸出相關:
| 函數 | 描述 | 例子 |
|---|---|---|
| print $STRINGS,... | 顯示文字 |
print "Hello, world\n";
print "This ", "is ", "my ", "first ", "program!\n";
print('Now is: ', localtime, "\n");
|
| printf $FORMAT, $ARGS,... | 格式化顯示資料 |
printf "Name: %s\nAge: %d\n", $name, $age;
printf("The cost is HKD%8.2f\n", $cost);
|
檔案/目錄相關:
| 函數 | 描述 | 例子 |
|---|---|---|
| -e $FILE | 檔案是否存在 | print "file exists\n" if -e 'file'; |
| -z $FILE | 檔案大小是零 (空檔案) | print "file is empty\n" if -z 'file'; |
| -s $FILE | 檔案大小不是零 | print "file is not empty\n" if -s 'file'; |
| -f $FILE | 檔案為一般檔案 (plain file) | print "file is plain file\n" if -f 'file'; |
| -d $FILE | 檔案為目錄 (directory) | print "file is directory\n" if -d 'file'; |
| -l $FILE | 檔案為符號連結 (symbolic link) | print "file is symlink\n" if -l 'file'; |
| -p $FILE | 檔案為 named pipe (FIFO) | print "file is named pip\n" if -p 'file'; |
| -S $FILE | 檔案為目錄 (directory) | print "file is socket\n" if -S 'file'; |
| -b $FILE | 檔案為區塊裝置 (block special file) | print "file is block device\n" if -b 'file'; |
| -c $FILE | 檔案為字元裝置 (character special file) | print "file is character device\n" if -c 'file'; |
| -t $FILE | filehandle 是指向 tty | print "standard input is tty" if -t STDIN; |
| -r $FILE | 是否為可以被有效 uid/gid 讀取的檔案 | print "readme is readable\n" if -r 'readme'; |
| -w $FILE | 是否為可以被有效 uid/gid 寫入的檔案 | print "editme is writable\n" if -w 'editme'; |
| -x $FILE | 是否為可以被有效 uid/gid 執行的檔案 | print "runme is executable\n" if -x 'runme'; |
| -o $FILE | 是否為可以為有效 uid 所擁有 | print "file is mine\n" if -o 'file'; |
| -R $FILE | 是否為可以被直正 uid/gid 讀取的檔案 | print "readme is readable\n" if -R 'readme'; |
| -W $FILE | 是否為可以被直正 uid/gid 寫入的檔案 | print "editme is writable\n" if -W 'editme'; |
| -X $FILE | 是否為可以被直正 uid/gid 執行的檔案 | print "runme is executable\n" if -X 'runme'; |
| -O $FILE | 是否為可以為直正 uid 所擁有 | print "file is mine\n" if -O 'file'; |
| -u $FILE | 檔案有設定 setuid | print "file has suid set\n" if -u 'file'; |
| -g $FILE | 檔案有設定 setgid | print "file has sgid set\n" if -g 'file'; |
| -k $FILE | 檔案有設定 sticky bit | print "file has sticky bit set\n" if -k 'file'; |
| chdir $DIR | 改變工作目錄 | chdir('/var/tmp'); |
| chmod $MODE, $FILES,... | 改變檔案權根 | chmod(0755, 'bin'); |
| chown $UID, $GID, $FILES,... | 改變檔案擁有者和所屬群組。$UID/$GID 為 -1 一般表示不改變該值 | chown(1001, 1001, @filenames); |
檔案存取相關:
| 函數 | 描述 | 例子 |
|---|---|---|
| close FILEHANDLE | 關閉檔案 |
字串處理:
| 函數 | 描述 | 例子 |
|---|---|---|
| chomp $STR | 切斷字串尾部的檔案紀錄分隔符 (記錄在 $/,一般為 "\n"),傳回值為切斷的字元數目。 |
while ( <> ) {
chomp; # 刪除尾部的新行字元 ("\n")
@fields = split(/:/);
}
|
| chr $NUM | 傳回 ASCII/UNICODE 為 $NUM 的字元 | chr(65) # 即 'A' |
自訂函數
sub force() {
my ($mass, $acceleration) = @_;
return $mass * $acceleration;
}
print "Force = %f\n", 5.0, 10;
參考資料
- ↑ GNU/Linux Manpage: perldata(1) - Perl data types


[SuSE][OpenSuSE] URL: http://search.cpan.org/dist/perl/pod/perldata.pod - ↑ GNU/Linux Manpage: perlvar(1) - Perl predefined variables


[SuSE][OpenSuSE] URL: http://search.cpan.org/dist/perl/pod/perlvar.pod - ↑ GNU/Linux Manpage: perldata(1) - Perl syntax


[SuSE][OpenSuSE] URL: http://search.cpan.org/dist/perl/pod/perlsyn.pod - ↑ GNU/Linux Manpage: perldata(1) - Perl syntax


[SuSE][OpenSuSE] URL: http://search.cpan.org/dist/perl/pod/perlfunc.pod
請參看
外部資料
页面分类: 未完成小作品 | Programming | Perl

