Perl 純量(Scalar)與陣列(Array)

Hello World! #!/usr/bin/perl # Hello World! # Perl:1980年代誕生,直譯式語言。 print "Hello World!\n"; # 雙引號可內嵌特殊字元 如: # \n Newline # \r Carriage Return # \t Tab # \f Formfeed # \b Backspace # \v Vertical Tab # \a Bell # \e Escape # \001 Octal ASCII value (here Ctrl-A) # \x20 Hex ASCII value (here space) # \cD Control character (here Ctrl-D) # \\ Backslash # \" Double Quote # \l Lowercase next letter # \L Lowercase all following letters until \E # \u Uppercase next letter # \U Uppercase all following letters until \E # \E Terminate \L or \U print 'Hello World!\n'; # 單引號則只能內嵌 \\ \' # 註一:在 Perl 中,函式可不用括號,以下兩行相等: # print "Hello World!\n"; # print("Hello World!\n"); # # 註二:在 Perl 中,"abc" 為三個字元,在 C 下, # "abc" 為三個字元加上一 Null 字元。 # Perl 單行註解為 '#' 開頭 # 多行註解為 =pod 此為註解 =cut 純量(Scalar) # 純量 (scalar) # (1) 純量:以 $ 開頭之變數,可儲存整數、浮點數、字串等 $val1 = 1; # 1 $val2 = 0x123; # 十六進位數值 123 # 為了使數字方便辨識,可加入 _ 分隔, # 此變數數值為 23323930 $val3 = 23_323_930; $val4 = -4.32e3; # 科學記號 $str1 = "AB"; # 字串 "AB" $name = "Bill"; print "Hello, $name\n"; # 雙引號可內嵌變數 print 'Hello, $name\n'; # 單引號不行 # (2) 數值與字串間的自動轉換 $a = "1"; # 字串 $b = "2"; # 字串 # Perl 會先將 $a 與 $b 自動轉為數值再相加,傳回數值 $c = $a + $b; $d = "12abc34"; # Perl 會略過 $d 內非數字起頭到結尾的部份, # 即 $d 被轉換為數值 12,再經計算 $e 為 24 $e = $d * 2; $f = "abc"; # 若完全不是數字的字串,會被轉換成零, # 因此結果 $f 被轉換為零,再經計算 $g 亦為 0 $g = $f * 2; $a = 1; # 數值 # Perl 會將 $a 轉為字串,做字串相加,$b 為 "string1" $b = "string" . $a; # 註:'.' 為字串相加運算子 # (3) 在字串內安插變數 $val = 12; $str1 = "I have $val dollars."; # 安插變數 $str2 = 'I have ' . $val . ' dollars.'; # 字串相加 $str3 = "def"; # Perl 有時容易誤判變數名稱 $str4 = "abc$str3ghijk"; # 加入 {} 之後,可讓 Perl 正確判斷安插變數名稱 $str5 = "abc${str3}ghijk"; # (4) 特殊變數 $_ $_ = "Bill"; print; # 若省略參數,預設為 $_,即 print $_; # (5) chomp,chop 刪除最後一個(換行)字元 $str1 = "hello world.\n"; chomp($str1); # 刪除最後一個換行字元,變成 "hello world." chomp($str1); # 無效果 chop($str1); # 刪除最後一個字元,變成 "hello world" chop($str1); # 刪除最後一個字元,變成 "hello worl" 陣列(Array) # 陣列(array) # (1) 陣列:'@' 開頭,一連串的純量 @empty = (); # 空陣列 # 一陣列內含兩元素 "Bill" "Mary" @arr1 = ("Bill","Mary"); # @arr2 = ("Bill","Mary","John") @arr2 = (@arr1,"John"); # @arr3 = ("John","Mary","Bill") @arr3 = reverse @arr2; # 按照 ASCII 碼排序,@arr4 = ("Bill","John","Mary") @arr4 = sort @arr2; print $arr1[1]; # "Mary" print $#arr2; # @arr2 最後一個元素的 index 即 2 print $arr2[$#arr2]; # @arr2 最後一個元素 print $arr2[-2]; # @arr2 倒數第二個元素 @arr4 = ("a","b","c","d","e","f"); @arr5 = @arr4[2..4]; # 取出 @arr4 第三到第五個元素 ($a,$b) = ($b,$a); # 交換 $a 與 $b # (2) 純量與陣列語境 @array = ("a","b","c"); # 陣列 $scalar1 = @array; # Perl 會傳回 @array 的長度 $scalar2 = sort @array; # Perl 會傳回 undef $scalar3 = reverse @array; # Perl 會傳回 "cba" $scalar4 = "@array"; # Perl 會傳回 "a b c" $scalar = "a"; # 純量 ($scalar); # 陣列,元素個數為一 # (3) pop,push,shift,unshift 陣列處理 @arr = (0,1); push(@arr,2); # push 後,@arr = (0,1,2) $a = pop(@arr); # pop 後,@arr = (0,1),$a = 2 @arr = (0,1); unshift(@arr,2); # unshift 後,@arr = (2,0,1) $a = shift(@arr); # shift 後,@arr = (0,1),$a = 2 # (4) split,join $str = "It's my life."; # 以空白做分隔,將 $str 切成陣列,存入 @arr @arr = split / /,$str; # 以 "-" 作分隔,將 @arr 連接成一個純量變數 $str2 = join "-",@arr;

April 23, 2015 · G. T. Wang

Perl 雜湊(Hash)與運算子

雜湊(Hash) # 雜湊 (hash) %hash1 = ("Bill", "boy", "Mary", "gril"); print $hash1{"Bill"}; # "boy" %hash2 = ("Bill" => "boy","Mary" => "gril"); # The same # %hash2 現在是 ("Bill" => "boy","Mary" => "gril","Joe" => "boy") $hash2{"Joe"} = "boy"; %hash3 = ("Joe" => "man"); # 合併 %hash2 與 %hash3,有重複的元素,會以最後一個為準 %hash2 = (%hash2,%hash3); keys %hash1; # 傳回一陣列,內容為 %hash1 的 key values %hash1; # 傳回一陣列,內容為 %hash1 的 value delete $hash1{"Bill"}; # 刪除元素 # exists 可測試元素是否存在 if(exists $hash1{"Bill"}) { print "exists"; } 運算子 # 運算子 # Arithmetic # + addition # - subtraction # * multiplication # / division # ** exponentiation $val = 2**3; # $val = 8 # Numeric comparison # == equality # != inequality # < less than # > greater than # <= less than or equal # >= greater than or equal # String comparison # eq equality # ne inequality # lt less than # gt greater than # le less than or equal # ge greater than or equal "abc" lt "bcd"; # true # Boolean logic # && and # || or # ! not # Miscellaneous # = assignment # . string concatenation # x string multiplication # .. range operator (creates a list of numbers) @arr = 1 .. 5; # @arr = (1,2,3,4,5); $str = "Bill" x 3; # $str = "BillBillBill"; # Many operators can be combined with a "=" as follows: # $a += 1; same as $a = $a + 1 # $a -= 1; same as $a = $a - 1 # $a .= "\n"; same as $a = $a . "\n"; # 註:其他運算子請參考 perlop(1)

April 23, 2015 · G. T. Wang

Perl 迴圈與控制結構

迴圈與控制結構 # 迴圈與控制結構 # (1) for for($i=0;$i<10;++$i){ print $i; # 印出 0123456789 } # 註:{} 不可省略 # (2) while # (A) $i=0; while($i<10){ print $i; # 印出 0123456789 ++$i; } # (B) while( ($key,$value) = each %hash ){ print "$key is $value\n"; } # (3) do while do { print $i; $i++; }while($i<10); # (4) until(與 while 相反) until($i>=10){ print $i; $i++; } # (5) foreach # (A) @arr = (1,2,3,4); foreach $i (@arr){ print $i; # 印出 @arr 所有元素 } # (B) %hash = ("Bill" => "boy","Mary" => "gril"); foreach $key (keys %hash){ # 印出 %hash 所有元素 print "$key is $hash{$key}\n"; } # (C) print foreach (1 .. 9); # 倒裝 # (D) foreach 可簡寫成 for print for 1 .. 9; # (6) last, next and redo while($something){ # redo 跳到這裡重新開始 # something ... if($ok){ next; # next 跳過目前此次迭代 } if($oops){ redo; # redo 重新執行目前此次迭代 } # something ... if($error){ last; # last 會終止圈 } # something ... # next 跳到這裡 } # last 跳到這裡繼續執行 # 註:next, last 與 redo 皆可用在 for,foreach,while 與 until 等迴圈。 # (7) if # (A) $a = 5; if($a > 3){ print "$a > 3\n"; }elsif($a < 3){ print "$a < 3\n"; }else{ print "$a = 3\n"; } # (B) $val = 3; # 倒裝,等同於: if ($val>0) { print $val; } print $val if $val > 0; # (8) unless (與 if 相反) $a = 5; print "$a > 4" unless($a <= 4); # 練習一 # # 1.寫一個 perl script 印出九九乘法表 # # 基本版 for($i=1;$i<10;++$i){ for($j=1;$j<10;++$j){ print $j . "x" . $i . "=", $i*$j, " "; } print "\n"; } # 排版整齊 for($i=1;$i<10;++$i){ for($j=1;$j<10;++$j){ print $j . "x" . $i . "=", $i*$j, " "; if($i*$j < 10){ print " "; } } print "\n"; } # 精簡版 for $i (1 .. 9){ printf "%dx%d=%-3d",$_,$i,$i*$_ for (1 .. 9); print "\n"; }

April 23, 2015 · G. T. Wang

Perl 標準輸入輸出與檔案輸入輸出

標準輸入輸出 # 標準輸入輸出 # (1) STDIN, STDOUT, STDERR print "Enter your name:"; $input = <STDIN>; # 從 STDIN 讀入 print STDOUT "Hello, $input"; # 輸出至 STDOUT # 註:print 預設輸出至 STDOUT # 把 STDIN 內容全部讀入 @all_lines,每一行為一個元素 @all_lines = <STDIN>; # 輸出至 STDERR print STDERR "This is an error!"; # (2) 鑽石算符 # 從參數指定之檔案讀入資料, # 若未指定檔案,則從標準輸入讀入資料 while(<>){ print; # 等同於 print STDOUT $_; } # 註:此 Perl script 相當於 cat # (3) printf 格式化輸出 $name = "Joe"; # Hello, Joe. printf "Hello, %10s.\n",$name; # Hello, Joe . printf "Hello, %-10s.\n",$name; # 註:輸出格式請參考 perlfunc(1) 檔案輸入輸出 # 檔案輸入輸出 # (1) 檔案代碼 (filehandle) # 開啟檔案,預設為讀入模式 open INFILE, "input1.txt"; # 從 INFILE 讀入一行 $line1 = <INFILE>; # 從 INFILE 讀入下一行 $line2 = <INFILE>; # 關閉檔案 close INFILE; # 以覆寫模式開啟檔案輸出 open OUTFILE, ">output3.txt"; # 把 $line1 寫入 OUTFILE print OUTFILE $line1; # 把 $line2 寫入 OUTFILE print OUTFILE $line2; # 關閉檔案 close OUTFILE; open INFILE2, "<input2.txt"; # 以讀入模式開啟檔案 # 把 INFILE2 檔案內容全部讀入 @all_line @all_line = <INFILE2>; close INFILE2; # 關閉檔案 # 以附加模式開啟檔案輸出 open OUTFILE2, ">>output4.txt"; # 把第一行附加至 OUTFILE2 之後 print OUTFILE2 $all_line[0]; close OUTFILE2; # 關閉檔案 # 開啟檔案,預設為讀入模式 open INFILE, "input1.txt"; while(<INFILE>){ print; # 將檔案讀入內容印出,相當於 cat } close INFILE; # (2) 使用 pipe open IN,"ls|"; # 把 ls 的輸出當作輸入 @file = <IN>; close IN; open OUT,"|sort -r"; # 把輸出導入 sort for(@file){ chomp; print OUT "<$_>\n"; } close OUT; # (3) DATA 檔案代碼 # 放在 perl script 檔內結尾處的資料,以 "__END__" 開始, # 使用方式即直接使用 <DATA> 檔案代碼。 while(<DATA>){ %hash = (%hash,split); } print "$_ is $hash{$_}\n" for keys %hash; __END__ Bill boy Mary girl Joe boy

April 23, 2015 · G. T. Wang

Perl 基本自訂副函式與排序(Sorting)

基本自訂副函式 # 基本自訂副函式 # (1) 基本自訂副函式 sub hello { # 自訂函式 print "Hello World.\n"; } &hello; # 使用自訂函式 # (2) my and local $name = "Joe"; # 全域變數 (Global Variable) sub hello { print "In hello: $name\n"; } sub hello2 { # 宣告 local 變數,在 hello2 本身及其呼叫的函式使用 local $name = "Bill"; print "In hello2: $name\n"; print "Call hello from hello2: "; &hello; } sub hello3 { # 宣告 my 變數,只能在 hello3 本身使用 my $name = "Mary"; print "In hello3: $name\n"; print "Call hello from hello3: "; &hello; } &hello; &hello2; &hello3; # (3) 自訂 max 函式 sub max { # 讀入參數:將 @_ 內的第一個與第二個元素讀入,剩下的捨棄 my($a, $b) = @_; if ($a > $b) { return $a; } else { return $b; } } print &max(1,2); # 2 排序(Sorting) # 排序(Sorting) # (1) @arr = (2,3,1,4); sub sort_by_number { # 排序副函式 if ($a < $b) { return -1; # 代表 $a 排在 $b 之前 } elsif ($a > $b) { return 1; # 代表 $a 排在 $b 之後 }else { return ; } } # 將 & 去掉使用,結果為 (1,2,3,4) @sorted = sort sort_by_number (@arr); @rev = reverse(@sorted); # (4,3,2,1) # (2) @arr = (2,3,1,4); sub sort_by_number2{ # 作用與 sort_by_number 相同 return $a <=> $b; } @sorted = sort sort_by_number2 (@arr); @rev = reverse(@sorted); # (3) @arr = (2,3,1,4); # Inline 方式撰寫排序副函式 @sorted = sort { $a <=> $b } (@arr); @rev = reverse(@sorted); # (4) hash 排序 %hash = ( Joe => 32, Mary => 87, Bill => 98, John => 67 ); sub by_grade{ return $hash{$a} <=> $hash{$b}; } @name = reverse sort by_grade keys %hash; print $_ . "\n" for(@name); # 練習 # 1. 假設有一成績資料檔案如下 =pod Joe 98 87 94 67 Mary 97 86 97 76 John 78 67 81 97 Bill 56 78 67 86 Seal 69 79 68 81 God 97 98 98 99 =cut # 總成績計算方式為: # 四次成績中刪去最低分的成績,剩下的三次做平均, # 請寫一個 perl script 來計算,並將輸出成績存入檔案。 # 假設成績檔為 score.txt open INFILE,"score.txt"; open OUTFILE,">output.txt"; while(<INFILE>){ ($name, @score) = split; @score = reverse sort {$a <=> $b} @score; pop @score; $sum = 0; foreach(@score){ $sum += $_; } $average = $sum / ($#score+1); print OUTFILE "$name\t$average\n"; } close OUTFILE; close INFILE;

April 23, 2015 · G. T. Wang