close

因為工作上的需要,user丟了一本O'reilly的Perl學習手冊(俗稱駱馬書)給我

 

只有半個月的時間要K完之後工作可能會需要用到的章節

 

所以我也只好很簡單的記了每一章節的key point

 

 

 

純量資料

1.所有數值均使用「倍精度浮點數」 => 1e-100 ~ 1e100
(ps:e為次方 , 1e100為10的100次方)

2.整數字面值(ps:在perl中即使輸入整數也會被perl轉換為「倍精度浮點數」去運算)
0
-40
255
61298040283768 => perl允許在數值中插入底線_,所以可以寫成 61_298_040_283_768

3. 非十進制的整數字面值

3.1 八進制(開頭為0) , 也可用Perl內建的函式oct()將十進位輸入後,轉成八進制
0377 #八進制的377 , 相當於十進制的255
0xff #十六進制的FF, 也相當於十進制的255
0b11111111 #也相當於十進制的255,perl也允許在當中插入底線_,
故也可寫成 0b11_111_111
3.2 十六進制(開頭為0x) , 也可用erl內建的函式hex()將十進位輸入後,轉成十六進制
0xff #十六進制的FF, 也相當於十進制的255

4. 單引號內的字串字面值
print 'he\nllo' #會印出he\nllo, 在單引號內的\n會被認作'\'及'n'兩個字符,

5. 雙引號內的字串字面值
5.1 除倒斜線緊接著的字符作用和單引號的不同外,其餘皆同
print 'he\nllo' #會印出 he
llo
5.2 變數安插

6.雙引號內字串的倒斜線規避字符
\n 換列
\r 回行首
\t 水平跳格
\f 跳頁
\b 退格
\a 鈴聲
\e Esc(ASCII編碼的規避字符 )
\007 任何八進制的ASCII(此例,007,表示鈴聲)
\x7f 任何十六進制的ASCII(此例,7f,表示刪除符號)
\cC 「控制」字符(此例表示Ctrl-C)
\\ 倒斜線
\" 雙引號
\l 將下個符號轉為小寫
\L 將到 \E為止的所有字符轉為小寫
\u 將下個字符轉為大寫
\U 將到 \E為止的所有字符轉為大寫
\Q 將到 \E為止的非單字(non-word)字符加上倒斜線
\E 結束 \L、\U或\Q

7.字串算符
7.1 字串相加:
1. "a" . "b"; #print ab
2. "a" . ' ' . "b"; #print a b
3. 'ab' . "\n"; #print ab\n

7.2 字串重複:
1. "alan" x 3 #x為小寫字符;alan重複相加3次,也就是"alanalanalan"
2. "alan" x (3+1) #alan重複相加4次,也就是"alanalanalanalan"
3. 5 x 4 # 5會被轉換成字串"5", 重複相加4次,也就是"5555"
# 數字的字串重複,會將數字先轉換成整數,再進行重複相加
#如 4.8 x3 , 會變成 "444"
4. "alan" x -1 #輸出空字串,當複製次數小於 1(負數),會產生長度為零的空字串

8.數值與字串間的自動轉換
8.1 使用數值的算符
1. "5" * "4" #輸出20,因為算符為 *
2. "12abc34" * "3" #輸出36,字串中前端非數字的部分會被略過
3. "abc34" * "3" #輸出0,因字串中最前端非數字,Perl直接判斷此為字串,非數字
8.2 數值與字串算符混合
"Z" . 5 * 7 #輸出 "Z35" , 牽扯到處理的優先順序

9. Perl的內建警告訊息
9.1 執行程式時啟用功能
perl -w abc
9.2 直接寫在程式內,讓程式每次執行時,都啟用警告功能
1. #!perl -w #在Unix以外的系統可以這麼寫
2. #!/c/Perl/bin/perl -w
9.3 在Perl 5.6,可在程式內利用warnrings打開警告功能
use warnings;
9.4 可利用Perl內建的diagnostics編譯命令看到較詳細的問題descrption
perl -Mdiagnostics singalStr #或是寫在程式中 use diagnostics

10. 變數
10.1 以$為開頭
10.2 第1個字母必須為字母(A-Za-z)或底線_
10.3 大小寫有分別
10.4 取值時,同樣以$取值
my $strTest = "123abc" * 4;
print $strTest;

11. 變數運算
$num = 10 #將$num值設為10
$Str = "alan" #將$Str值設為含有4個字符"alan"
$count = $num + 5 #$count的值會= 15
$Streql = $Str * 3 #Streql的值會等於"alan"*3=>"alanalanalan"

12. 二元賦值算符
1.
$num = 10
$num += 5 #$num的值會變為15
2.
$Str = "A"
$Str *= 3 #Str的值會變為"AAA"

3.
$Str = "A"
$Str .= "\n" #在"A"的後面附加一個"斷行符號"

4. 乘冪運算
$_strTest = 5;
$_strTest **= 3; #將5連乘3次(5*5*5), $_strTest = 125

13. Print的串列
print "The answer is ", 6*7, ".\n"; #會輸出 The answer is 42.

14. 字串裡安插純量變數
1.第一種寫法
$meal = "bro steak";
$alan = "alan ate a $meal"; #會輸出alan ate a bro steak
2.第二種寫法
$meal = "bro steak";
$alan = "alan ate a " .$meal; #會輸出alan ate a bro steak

3.想印出"fred ate 3 steaks

$what = "steak";
$n = 3;

錯誤寫法: print "fred ate $n $whats.\n";
正確一: print "fred ate $n ${what}s.\n";
正確二: print "fred ate $n $what" ."s.\n";

15. 比較算符

比較 數值 字串
============================
相等 == eq
不等 != ne
小於 < lt
大於 > gt
小於或等於 <= le
大於或等於 >= ge

if($name gt 'fred'){
print "'$name' 排在 'fred' 後面. \n";
}else{
print "'$name' 排在 'fred' 前面或相同位置. \n";
}

16.布林值
Perl並沒有Java的boolean值(true,false)
單純以0(false),1(true) 來當做布林值
$is_bigger = 1; # 這裡的1也可以字串的 "1"代替

if($is_bigger){
print "此為true";
}else{
print "此為false";
}

17. 取得使用者輸入(使用<STDIN>)
$line = <STDIN>;
if($line eq "\n"){
print "只是一個空列\n";
}else{
print "你輸入了: $line" ;
}

18. chomp算符,只能處理字串
18.1 去除換行符號
$text = "abc\n";
chomp($text);
18.2 和上面同樣寫法
chomp($text = <STDIN>);

18.3 函式的括號可以加也可以不加
print chomp $text;

19. while
$count = 0;
while($count < 10){
....
}

20. undef(未定義)
字串 = ""
數值 = 0

21.defined函式
此函式會對undef傳回0,判斷某個字串是undef而不是空字串""
if(defined($name)){
print "非undef";
}else{
print "沒有可用的輸入";
}

22. List

23. Array
23.1存取array中的element
1.
$fred[0] = "yahoo";
$fred[1] = "pchome";
$fred[2] = "google";

print $fred[0]. "\n";
print $fred[1] .= " online";

2.雖然$index不是整數,perl會自動捨去小數部分
$index = 2.34566;
print $fred[$index - 1]; #印出pchome

23.2 特殊的陣列Index
1.必要時$fred[3] - $fred[98]的array會自動產生,並設成undef值
$fred[0] = "yahoo";
$fred[1] = "pchome";
$fred[2] = "google";
$fred[99] = "rock";

print $fred[88]; #印出空字串

2.
$end = $#rocks; #array的最後一個元素
$number_of_rock = $end +1; #array的最後一個元素 + 1 ==> 繞到array的第一個element==> $fred[0]
print $fred[$end]; #印出$fred[99] ==>rock
print $fred[$number_of_rock]; #印出$fred[0] ==> yahoo

3. 負數陣列Index

$fred[0] = "yahoo";
$fred[1] = "pchome";
$fred[2] = "google";
$fred[3] = 'black & white ';

print $fred[ -1]; #印出black & white

23.3 串列字面值
1. (1,2,3) eq (1,2,3,) #最後一個逗點","會被忽略
2.(1..5) #與(1,2,3,4,5)相等
3.(1.7..5.7) #與上列相等,小數點.7會被忽略
4.(0,2..6,10,12) #與(0,2,3,4,5,6,10,12)相等
5.(0,..$#rocks) #0 ~ 最後一個陣列
6.("rocks", "fred", "mac") #字串array

23.4 @rray的變數賦值
@rocks = qw/ rock1 rock2 rock3 /; # 在rock前加上「@」, 表示取得rock的整個陣列
# qw/ ..... / 則是取代上列以雙引號做為字串array的麻煩,
#以空白代替「,」
#常用的有 qw﹝! # ( { [ <﹞
print @rocks[0];

24. pop 取出array中最後的值,並將值從array中刪除
@array = 5..7;
$fred = pop(@array); #$fred的值為7 , @array剩5、6
pop(@array); #@array剩5
pop(@array);
$alan = pop(@array); #因@array中已無值,故$alan會得到undef

25. push 將值放至array的最後
@array = 5..6;
push @array,8; #array變成5、6、8;
push (@array,1..3); #array變成5、6、8、1、2、3;

26. shift & unshift 功能和pop、push類似,pop和push是將值放在array的最後面,相反地,
shift和unshift是將值放在array的最前面

@array = qw# dino fred #;
$x = shift @array; #$x 為dino, @array剩fred
$y = shift (@array); #$y 為fred, @array已經無值
$z = shift @array; #$z 為undef

unshift @array,5; #@array的值為5
unshift (@array,4); #@array的值為4、5
unshift @array,1..3; #@array的值為1、2、3、4、5

27. 在字中內安插陣列的問題
@fred = qw(eating rocks is wrong);
$fred = "right";
print "this is $fred[3]\n"; #會印出 this is wrong
print "this is ${fred}[3]\n"; #會印出 this is right[3]
print "this is $fred"."[3]\n"; #會印出 this is right[3]
print "this is $fred\[3]\n"; #會印出 this is right[3]

28. foreach
@rocks = qw(bedrock slate lava);
foreach $rock (@rocks){ #此處的@rocks會依序將array中的值以call by reference的方式將value傳到$rock
$rock = "\t$rock";
$rock .= "\n";
}

print "石頭清單: \n", @rocks;

29. Perl的預設變數($_)
foreach(1..10){
print "報數: $_ \n";
}

$_ = "it is awsome\n";
print; #print預設變數的值

30. reverse 將array的值,依相反的順序傳回至array
@fred = 1..6;
@fred = reverse @fred; #@fred的值變成6 5 4 3 2 1

31. sort 1.數字,從1至9排序 ,
2.根據ASCII編碼的字串,大寫字排在小寫字的前面
3.數字排在字母前面

@rocks = qw(bedrock slate rubble granite);
@sorted = sort @rocks; #@sroted的值為bedrock granite rubble slate
@back = reverse sort @rocks #@back的值從slate排到bedrock
@number = sort 97..102; #變成 100 101 102 97 98 99

32. 純量語境與串列語境
在perl中,究為「純量語境」還是「串列語境」,須就程式的情境而定,以下列的例子說明,
sort @people是針對「串列」做對處理的對象,回傳的值也是「串列」,
故@strted得到的值也必為「串列」。

一般運算符號(+ - * /),是針對「純量」做為處理的對象,回傳的值也是「純量」,
故$number 得到的值也必為「純量」。

@people = qw( fred bb aa);
@sorted = sort @people; #@sorted 的值為aa bb fred
$number = 42 + @people; #$number的值為45(42 + @people的陣列數量[3])

print @people;
print "\n";
print $number;

32.1 在純量語境下使用原本應該使用於「串列語境」的運算式
1. use sort
$number = sort "abcd"; # sort在純量語境下使用的結果,sort只會回傳undef , 故$number會得到undef

2. use reverse
@backwards = reverse qw(yabba dabba doo); #@backwards得到的值為 doo,dabba,yabba
$backwards = reverse qw(yabba dabba doo); #$backwards得到的值為oodabbaabbay

32.2 scalar 告訴Perl要取得「串列語境」的「純量語境」
@rocks = qw(talc quartz jade obsidian);
print "有 ", scalar @rocks ,"種石頭!!\n"; #會列印 "有4種石頭"

33. 「串列語境」下的<STDIN>
最簡潔的寫法
chomp(@lines = <STDIN>); #讀取所有資料列,但不包含換列字符

34. 副常式
34.1 定義 sub & 呼叫
sub marine{
$n += 1; #global varible
print "水手 $n 報到!! \n";
}

副常式的定義具全域性,ex :declaration $n
(除非使用某些強制性技巧)

呼叫(call)marine
&marine; #水手 1 報到!!
&marine; #水手 2 報到!!
&marine; #水手 3 報到!!
&marine; #水手 4 報到!!
&marine; #水手 5 報到!!


34.2
1. 副常式沒有分「有傳回值」和「無傳回值」,一定都會有回傳值,故無須在method name前面加註任何語法區分
2. 最後一次運算的結果會被自動當成副常式的return value

sub subOfFredAndBarney{
print "你呼叫了 subOfFredAndBarney 副常式! \n";
$fred + $barney; #回傳值
}

$fred = 3;
$barney = 4;
$c = &subOfFredAndBarney; #c為7
print "C的值為 $c !!\n";

$d = 3 * &subOfFredAndBarney; #d為21
print "D的值為 $d !!\n";

34.3 必須注意的很重要一點: 在perl中,會將最後執行的運算結果傳回,但如果最後一行為「print」
perl會回傳「1」(代表列印成功),

sub subOfFredAndBarney{
print "你呼叫了 subOfFredAndBarney 副常式! \n";
$fred + $barney; #本來應該回傳這個值
print "怎麼了??? \n"; #現變成回傳1
}

$fred = 3;
$barney = 4;
$c = &subOfFredAndBarney; #$c 為 1
print "C的值為 $c !!\n";

$d = 3 * &subOfFredAndBarney; #d為3
print "D的值為 $d !!\n";

34.4 副常式和if,

sub largerOfFredOrBarney{
if($fred > $barney){
$fred; #如果$fred的值較大,就回傳$fred
}else{
$barney; #如果$barney的值較大,就回傳$barney
}
}
34.5 sub method引數(其實引數進入sub method時會存到[@_]的特殊array,但如要單獨指明要取用哪個index的引數時,則以 $_[index] 存取)

sub max{
if($_[0] > $_[1]){ #引數的承接以$_[int index]做為變數
$_[0]; #$_[0]的值為 10
}else{
$_[1] #$_[1]的值為 15
}
}

$n = &max(10,15); #call method max,並放入兩個引數


34.6 sub裡的private varible[my]

sub max{
my($m,$n); #$m 及 $n只存在於max 這個sub method
($m,$n) = @_; #將參數賦值給$m及$n
#my($m,$n) = @_; #可以將上述兩行整合成一行
if($m > $n){
$m;
}else{
$n;
}
}

34.7 檢查引數的值
sub max{
if(@_ != 2){
print "警告! &max 應該只有兩個引數!\n";
}

}

34.8 讓sub method接受任意數目的引數
$maximun = &max(3,5,10,4,6);

sub max{
my($maxSoFar) = shift @_; #取得array的第一個值
foreach(@_){ #檢視其餘的引數
if($_ > $maxSoFar){
$maxSoFar = $_; #一步步將array中最大的值放到$maxSoFar
}
}
$maxSoFar;
}

34.9 about my in block varible

sub max{
my($num) = @_; #會取得@_的第一個值
print "max: $num\n"; #會print 5
}

sub max2{
my $num = @_; #會取得@_的index的個數
print "max2: $num\n"; #會print 3
}

&max(5,9,12);
&max2(5,9,12);

34.10 use strict編譯命令: 藉use strict要求Perl維持一點程式撰寫的紀律
例如:
1.在sub method裡,perl會強制要求每個變數都要使用my來宣告新的變數
2.大部份的字串都必須放進引號

#建議只要程式碼超過一頁螢幕,都要在一開始的地方加上 use strict

34.11 return 算符
在迴圈中只要看到return,就提前傳回值

sub whichElementIs {
my($what, @list) = @_;
foreach(0..@#list){
if($what eq $list[$_]){
return $_; #一執行到這行,就直接傳回值,並跳脫foreach
}
}
-1; #查無該元素,回傳-1 (也可使用 return -1)
}

34.12 省略call sub method時的 "&"
1.call method時,放入引數
my @cards = shuffle(@desc_of_cards); #很明顯shuffle是個method

2.Perl已看過sub method的宣告
sub division{
$_[0] / $_[1];
}
my quotient = division 355, 113 #使用&division , 且連括號都省略了

34.13 不可省略"&"
當自己宣告的sub method和Perl提供的method同名時,在call sub method時,絕不可省略
sub chomp{
print "abc";
}

&chomp;

35. IO
35.1 讀到檔案結尾就跳離迴圈
while(defined($line = <STDIN>)){
print "看到 $line";
}
#上面的程式也可替換成
while(defined($_ = <STDIN>)){
print "看到 $_";
}

35.2 <STDIN> 和 <>
perl的輸入有<STDIN> 和 <>

35.3 鑽石算符(<>)會先去找"@ARGV"(讀取檔案) , 如果"@ARGV"是空字串,才會改用標準輸入串流
@ARGV = qw# larry moe curly#; #會去讀取larry , moe , curly這3個檔案
while(<>){
chomp;
print "我所看到的是 $_!\n";
}

35.4 標準輸出
1.
@array = qw(java perl php);
print @array; #會印出沒有空格的陣列內的字串, "javaperlphp"
print "@array"; #會印出有空格的陣列內的字串, "java perl php"
2.
print (2+3 ) * 4; #這是個錯誤的寫法,Perl當加了()後,會調用method來處理,
#比如這個寫法,perl會先印出 5 後,再判斷print的method是否成功印出,
#如果成功印出,則會回傳1, 此時, 1再乘4 ,最後再將1*4的乘積丟掉,
#除非改成 $result = print (2+3 ) * 4; #$result的值會等於4

print ((2+3 ) * 4); #這樣才是正確的寫法, 會印出20

3. 再次強調, 最好使用-w 或 use warnings除錯

4. printf , 跟C的printf是一樣的功能
常用的參數 :
(1) %g #perl會依需要自動選擇浮點數、整數、指數
printf "%g %g %g \n " , 5/2, 51/17, 51 ** 17; #2.5 3 1.0683e+29

(2) %d #十進制的整數,小數點無條件捨去
printf "在 %d 天內!\n", 17.85 ; #在 17 天內

(3)指定寬度,但如果資料太長,欄位會依需要自動擴大
printf "%6d\n", 42; #輸出 ----42 (ps:-代表空格)
printf "%2d\n", 987654; #輸出987654

(4) %s #字串
printf "%10s\n","alan"; #輸出 ------alan
printf "%-15s\n", "peng"; #輸出 peng----------- (當寬度欄位為負數時,表將插入的字串放在最左邊)

(5) %f #浮點數,小數點4捨5入
printf "%12f\n", 6 * 7 + 2/3; #輸出 ---42.666667
printf "%12.3f\n", 6 * 7 + 2/3; #輸出 ------42.667 (ps:%12.3f , 表只要輸出至小數點3位,第4位要4捨5入)
printf "%12.0f\n", 6 * 7 + 2/3; #輸出 ----------43 (ps:%12.0f , 表只要不輸出小數點,但小數點第1位要4捨5入)

(6) %% 輸出%符號
printf "月利率: %.2f%%\n", 5.25/12; #輸出0.44%

5. 開啟檔案代號
檔案代號的保留名稱: STDIN、STDOUT、STDERR、DATA、ARGV、ARGVOUT
#在取檔案代號名稱時,應避免取以上6個名稱

open CONFIG, "abc";
open CONFIG, "<abc"; #和上面的方式一樣
open BEDROCK,">fred"; #開啟檔案BEDROCK,並輸出到檔案fred(如果無檔案fred時,則會新建fred, 若有檔案fred,則覆蓋fred)
open LOG, ">>logfile"; #append log到logfile

6. 關閉檔案代號
close BEDROCK; #當close時,Perl會執行類似java的flush(出清緩衝區)的功能

7. 用die處理嚴重錯誤(就是程式根本無法正常執行,在輸出錯誤訊息後,直接將程式關閉)

if(! open LOG, ">>logfile"){
die "無法建立 Log File: $! "; # "$!" 系統的錯誤訊息
}

if(@ARGV < 2){
die "參數不足\n";
}

8. warn 送出警告訊息 , 並不會停止程式的執行

9. 使用檔案代號
open TESTFILE, "<abc"
or die "檔案無法開啟: ($!)";

while(<TESTFILE>){
chomp;
print $_;
}

檔案abc的內容為 alan irene ring

10. 改變預設的輸出檔案代號
Perl預設的輸出檔案代號為STDOUT,但可以透過select改變, 但﹝駱馬書﹞不建議這麼做
select BEDROCK;
print "ooxx !!\n";

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 射手奶爸 的頭像
    射手奶爸

    奶爸的部落格

    射手奶爸 發表在 痞客邦 留言(0) 人氣()