續上一篇的運算子#1,另外十種運算子。
12.位元運算子 & | ^
進行位元運算會用到,結果可以參考 [PERL] 位元運算 Bitwise operation,常會被搞錯的是 '^' 不是指數,而是XOR。
13.邏輯運算子 && ||
條件判斷中常會用到的運算子,這和上面的位元運算子有一點不同。有時可以用and代替&&;or 代替 ||,兩者差別是 and/or 的優先權是運算子中最低的。
|| 在perl 的運算規則中還有另一個意義,就是傳回第一個「評估為true的結果」:
例如
$v= defined $a || defined $b || "預設字串" || die "no value";
因為 $a, $b 都沒有定義,所以 $v ="預設字串",最後一個die 是根本不會執行到,多此一舉。但可以用這種方法決定預設值。
另一個常見的用法,在開啟檔案時常會這樣寫:
open("inFILE", './somefile.txt') || die "Can't open file: $!\n";
意思會先去開檔案,開不成功第1個項目會是FALSE,再處理第二個項目 die~~~
&& 在perl 的運算規則中也有另一個意義,就是傳回第一個「評估為false的結果」, 不過我不知道要用在哪!
14.範圍運算子 .. ...
範圍運算子又稱flip-flop operator,有兩種表示法:兩個點 '..' 或是三個點 '...',其組成是:
左運算元 ... 右運算元
範圍運算子很難理解清楚,官網上是這樣寫:
左運算元、右運算元就像是一個開關,只要左運算元成立,就打開開關( 為 true);到右運算元成立,則關閉開關 (false)。而兩個點 .. 左邊使開關打開後,"同時"會再比對右運算元,看是否成立,若右運算元成立,就會把開關關閉;使用三個點,則會在左邊開關打開後,同字串就不再驗證右邊運算元。也就是關閉的開關要交給後面的變數來決定。
說真的我看不太懂 > <,但我知道可以怎麼用:
指定陣列
陣列是以 '@'符號作開頭,在後面的單元會再介紹。
@array = (1..10); # 產生一個 1,2,3...10的數字陣列 @array = ('01'..'10'); # 產生一個 01,02,03...10的字串陣列 @array = ("A".."J"); # 產生一個 'A','B' .. 'J''的字元陣列 @array = ("AX".."BJ"); # 產生一個 'AX','AY','AZ','BA' .. 'BJ''的字串陣列
列表
代表一個範圍,可以做出神奇的功能
for (101 .. 200) { print; } # 101102103...200
放在for裡面的範圍運算子就相當於這樣:
for($i=101;$i<=200;$i++){ print $i; }
陣列的切片
這個運算子可以輕易的做出切片(array_slice)的功能
@array = ('01'..'20'); # 產生一個 01,02,03...20的數字陣列 @slice= @array[4..12]; #切出第4到第12 print @slice; # 050607080910111213 @slice= @array[-5..-1]; #切出倒數第5到尾端 print @slice; #1617181920
15. (三元)狀態運算子 ?:
三元運算子很容易,常用的寫法:
$comment = $score>=60 ? '及格' : '不及格';
意思是先判斷變數$ok的真假,如果真的話 $a=$b,如果$ok為假,則$a=$c。
三元運算子有時可以取代if..else的使用,同時它也有逆向的寫法:
($ok ? $a : $b) = $c;
意思是先判斷變數$ok的真假,如果真的話 $a=$c,如果$ok為假,則$b=$c,反向來決定$a或b何者為$c。
16. 指派運算子,有 = += -= *= 等
有這些可以用 = **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x=
舉個例,原本的式子是讓$a *5。
$a = $a*5;
簡化為指派運算子寫成
$a *= 5;
這樣看起來簡單也易讀。有些指派運算子是PERL專有的,例如:
$a=12; $a **= 2; # 144,$a的2次方 $a=12; $a %= 10; # 2,餘數除法餘10餘2 $a=12; $a &&= 3; # 3 $a=12; $a &= 2; # 0 $a=12; $a |= 2; # 14 $a=12; $a ||= 3; # 12 $a = 12; $a x= 5; # 1212121212 12印5次
第3行和第7行在前面的第13項「邏輯運算子」中有提過,具有評估的功用,||是會回傳第一個為真的結果,&&是第一個為真的話回傳第2個結果,所以
$a &&= 2; 等同於 $a = $a && 3; 因為$a=12必為真,所以傳回第2個結果3
$a ||= 3; 等同於 $a = $a || 3; 因為$a=12必為真,所以傳回第1個結果12
第4行和第6行是位元運算
$a &= 2; 等同於 $a = 12 & 2; 以二進位表示 $a= 1100 & 0010,等於0000=>0
$a |= 2; 等同於 $a = 12 | 2; 以二進位表示 $a= 1100 | 0010,等於1110=>14
17. 指定運算 =>
前面提過的,常數在指定值時有用到 '=>' ,這是一個指定運算,使用的時機不多
use constant FOO => "something";
另外在PERL hash (中文叫「雜湊」,後面的章節會介紹) 中會用到:
%h = ( 'John' => 23, 'Tom'=>30, 'Mary' => 25 );
要注意的是指定運算符號'=>'和第1項「物件指標」符號'->'不一樣,不要寫錯了。
18.清單運算子
清單運算子(list operator)在PERL是一種怪異的存在,而且還有分方向向左和方向向右兩種。無論哪種方向都是以逗號','作為分隔。
方向向左
基本上只要是逗號分隔的清單在PERL裡會視為向左的清單運算子。但向左的清單運算子優先權是最高的,放在這只是為了比較。
print "this","is",1, "book"; # thisis1book @ary = (1, 3, sort 4, 2); print @ary; # prints 1324
方向向右
方向向右的清單運算子有時不好理解,其實這是PERL本身沒有所謂的函式,有副程式要傳參數進去時的一種替代方式。例如開檔案時會這樣寫:
open HANDLE, "filename" or die "Can't open file\n";
這裡的HANDLE, "filename" 就是要傳給open這副程式的參數,由於他的優先權還高於or,因此可以省略小括號。如果要用||代替or,小括號就不能省:
open (HANDLE, "filename") || die "Can't open file\n";
的確不好理解吧。
19.符號運算子 not
這個和邏輯算子 ! 同義,只是優先權非常低。
20 邏輯運算子 and
這個和邏輯算子 && 同義,只是優先權非常低。
21.邏輯運算子 or xor
and 和 or的運算子優先權最低,寫的時候一定要特別小心,否則除錯會除死人:
$a = $b && $c; # 等於 $a = ($b && $c); 正確 $a = $b and $c; # 等於 ($a = $b) and $c; 這不是你要的 $a = $b || $c; # 等於 $a = ($b || $c); 正確 $a = $b or $c; # 等於 ($a = $b) or $c; 這更不是你要的
所以使用上除非有把握,不然not and or xor這些運算子少用點。
運算子這兩篇花了我非常多的時間,希望初學者能很快的了解,雖然範圍運算子我還不是很清楚啦!
的確,PERL的運算子有些真的很難理解,也不是這麼好用,像是有名稱的一元運算子、推位運算子、範圍運算子等。如果用法不清楚或是沒把握它的優先權的話,建議是先加個小括號來確保。
延伸閱讀