運算子(operator) 又稱算符,是不是每個語言都差不多?一般言是大同小異,perl有一些別的語言沒有的運算子,例如:
x 單一個英文字母'x',代表是「重覆」的意思
.. 兩個點,代表「範圍」
... 三個點,也代表「範圍」
=~ 比對判斷
我整理了運算子,其中:
1. 運算子的優先權由上到下
2. 同一行由左到右列
3. 性質和C-like略有不同的運算子以粉色底表示
總共有21種,介紹如下:
1. 物件指標 '->'
物件指標有最高的優先權,例如 $obj 的 func() 副函式:
$obj->func();
2. 自動加減運算子 ++ --
這個大家應該不陌生,++/--可置於變數前或後,例如 $ii++或 ++$ii 結果是一樣的,差別在於運算子寫在前面的會先運算完再回傳值:
$ii=1; $v= ++$ii; #$v=2 $ii=1; $v= $ii++; #$v=1
但Perl 還可以對 ++ 做更奇怪的計算(-- 不適用),如果目標是1字串,且2符合這個規則/^[a-zA-Z]*[0-9]*$/,好像是EXCEL的欄位編號:
print ++($foo = 'a0'); # prints 'a1'
print ++($foo = 'Az'); # prints 'Ba'
print ++($foo = 'zz'); # prints 'aaa'
3. 指數運算子 **
指數運算子由兩個星星符號'**'來代表,不是一般會用的'^',例如 $ii 的四次方寫作 $ii**4。指數運算子的優先權很高,所以:
print -2**4; #-16 print 2**2*3; #12
4. 符號運算子 ! ~ \ 正負號 + -
! 和 NOT 同義,差別只是優先權 !高,是邏輯上的相反,比較要注意的是他們的相反值可不是你想的0或1
$a=undef; print "Y\n" if defined( $a); # print nothing print !$a; # !$a =1 $a=1; print !$a; # !$a = "" 空值,但是不為 undef print "Y\n" if defined( !$a); # print Y $a=""; print !$a; # !$a =1 空值的 ! 反而變成 1
~ 是補數運算,可參考 [PERL] 位元運算 Bitwise operation 最下面
print ~1; # 18446744073709551614
\ 是指標運算,可以讓變數變成位址參照,類似C的位址位址符號 '&',例如:
$scref = \$foo;
$arrref= \@ARGV;
5. 比對運算子 =~ !~
PERL最厲害的比對用運算子,在 [PERL] 04-基本比對 有提到。
6. 乘除運算子 * / % x
% 是餘數除法,很多語言都有,正數沒問題 10%8=2;但負數就要注意了, -10 %8=6
PERL定義 $a % $b 為 $a 減去$b 的倍數中最小於$a且最接近 $a 的值,所以 -10 % 8=6;
x 是字串重覆乘法
print '-' x 40; # 印40個'-' $a = 1 x 10; # 1111111111
解法一 先減掉餘數再除 ($a - ($a % $b)) / $b 這種作法遇到負數會有問題,例如 -10整除8 =-2
解法二 使用 int 函數,int 是取浮點數的整數部分,例 int (-10/8) =-1 ,看來沒問題,但是看看下面這個範例:
print -6.725/0.025; # -269
print int -6.725/0.025; #-268 ,原來用int 系統算出來的值會是 -268.99999999999994315658 所以這個函數也不能用
解法三 使用 sprintf 函數 $result = sprintf("%.0f", -6.725/0.025); # -269 是正解,還真不容易。
7. 加減運算子 + - .
. 是字串相黏運算子
8. 推移運算子 << >>
聽說常會用這個的都是高手
$a=9; $a>>1; #4 $a=9; $a<<1; #18
9. 有名稱的一元運算子 (named unary operators)
這是 perl 裡很有特色的運算子,也可以當他是只有一個參數的函數,其實我沒完全搞懂,但倒是常常在用,例如 localtime, sleep, scalar, int...
有名稱的一元運算子優先權很高,但注意print 不是有名稱的一元運算子,他是一個串列運算子,看吧!不是這麼容易分清楚的。
看人家的範例,rand是一個產生亂數的函數,如果要寫出正確的結果,就要看懂下面的差異,如果真的搞不清楚,就用第二式的寫法,把rand 當函數來用就好了。
rand 10 * 20; # rand (10 * 20) rand(10) * 20; # (rand 10) * 20 rand (10) * 20; # (rand 10) * 20 rand +(10) * 20; # rand (10 * 20)
PERL裡面還有一種很特別的叫作檔案測試運算子,是由一個減號和英文字母組成,和你在SHELL常會看到的差不多:
-w | 檔案或目錄, 對目前 (有效的) 使用者或群組來說, 是可寫的.
-e | 檔案或目錄是存在的
-f | 檔案代號是文字檔
-d | 檔案代號是目錄
這些運算子可以參考[1],例如判斷檔案是否為文字檔:
if( -f '/path/to/your_file.txt'){ ... }
判斷該名稱是否為目錄:
print "是一個目錄" if -d '/home/axer';
10.比較運算子 < > <= >= lt gt le ge
在 [PERL] 03-條件式判斷中已有提過這個運算子,相信大家已經不陌生了。
11.比較運算子 == != <=> eq ne cmp
同上,數值的比較用 == != ,字串的比較用 eq ne;
<=> 是數值的比較。如果左邊大傳回1;相等傳回0;左邊較小傳回-1
cmp 字串的比較。如果左邊大傳回1;相等傳回0;左邊較小傳回-1
$left=9; $right=12; print $left <=> $right; # -1 print $left cmp $right; # 1
先介紹11組的運算子,接下來介紹另外10組
參考資料
[1] https://puremonkey2010.blogspot.tw/2010/09/perl-ch12.html