Perl 程式設計/運算子
Perl 的運算子集大量借鑑了 C 程式語言。Perl 透過為字串函式注入新的運算子來擴充套件它 (.=, x, eq, ne等)。相比之下,C 將其 Perl 功能子集委託給庫 strings.h 和 ctype.h,並且預設編譯時不包含此類功能。Perl 還包括一個高度靈活的 正則表示式 引擎,它受 Sed 的啟發,並對標準 POSIX 正則表示式進行了改進,最值得注意的是對 Unicode 的支援。
大多數算術運算子是二元運算子;這意味著它們接受兩個引數。一元運算子只接受一個引數。算術運算子非常簡單,通常是透明的。
所有基本算術運算子,加法 (+),減法 (-),乘法 (*) 和除法 (/),以及模運算子%都存在。模運算返回除法 (/) 運算的餘數。
# 3 goes into 4, 1 time with 1 left over.
print 4%3; # prints 1
# 2 goes into 4, 2 times with 0 left over.
print 4%2; # prints 0
# 3 goes into -4, -2 times with 2 left over.
print -4%3; # prints 2
冪運算子是**。它允許您將一個值提升到另一個值的冪。如果將分數提升到冪,您將得到該數的根。在本例中,第二個結果提升到 2 的冪後應該返回 2 ((2**(1/2))**2 = 2).
# Four squared:
print 4**2; # prints 16
# Square root of 2
print 2**(1/2); # prints 1.4142135623731
函式sqrt用於查詢平方根。其他分數冪(即(1/5)、(2/13)、(7/5)以及類似的冪)可以使用**運算子適當地找到。
自動遞減 (--) 和自動遞增 (++) 運算子是一元運算子。它們將它們操作的標量變數改變一個邏輯單位。在數字上,它們加或減一。在字母和字串上,只有自動遞增會將字母表中的字母向上移動一位,並且具有回滾的能力。在後綴和字首中出現的運算子可以使用兩種方式。第一種方式返回變數在更改之前的值,第二種方式返回變數在更改之後的值。
my $foo = 1;
# post decrement (printed and then decremented to 0)
print $foo--; # prints 1
print $foo; # prints 0
my $foo = 1;
# pre-decrement (decremented to 0 then printed)
print --$foo; # prints 0
print $foo; # prints 0
my $foo = 'd';
# pre-increment (incremented to e then printed)
print ++$foo; # prints e
print $foo; # prints e
my $foo = 'Z';
# post-increment (printed the incremented to AA)
print $foo++; # prints Z
print $foo; # prints AA
基本賦值運算子是=,它將左側的值設定為等於右側的值。它還返回該值。因此,您可以執行以下操作$a = 5 + ($b = 6),這將設定$b的值為 6,而$a的值為 11 (5 + 6)。為什麼您要這樣做是另一個問題。
來自 C 的賦值更新運算子,+=, -=等在 perl 中有效。Perl 擴充套件了這個基本思想,以包含 perl 中的大多數二元運算子。
| 運算子 | 名稱 |
|---|---|
| += | 加法賦值,加等於 |
| -= | 減法賦值,減等於 |
| *= | 乘法賦值 |
| /= | 除法賦值 |
| %= | 模運算賦值 |
| **= | 指數賦值 |
| .= | 連線賦值 |
| x= | 重複賦值 |
| &&= | 邏輯 AND 賦值 |
| ||= | 邏輯 OR 賦值 |
| &= | 位 AND 賦值 |
| |= | 位 OR 賦值 |
| ^= | 位 XOR 賦值 |
| &.= | 位字串 AND 賦值 |
| |.= | 位字串 OR 賦值 |
| ^.= | 位字串 XOR 賦值 |
| <<= | 左移賦值 |
| >>= | 右移賦值 |
| //= | 定義 OR 賦值 |
my $foo = 'Hello';
$foo .= ', world';
print $foo; # prints 'Hello, world';
my $bar = '+';
$bar x= 6;
print $bar; # prints '++++++';
Perl 使用不同的運算子來比較數字和字串。這是因為在大多數情況下,Perl 會很樂意字串化數字和數值化字串。在大多數情況下,這很有幫助,並且與 Perl 的DWIM Do-What-I-Mean 主題一致。不幸的是,在一個地方,這通常沒有幫助,那就是比較。
| 名稱 | 數值 | 字串 |
|---|---|---|
| 等於 | == | eq |
| 不等於 | != | ne |
| 小於 | < | lt |
| 大於 | > | gt |
| 小於或等於 | <= | le |
| 大於或等於 | >= | ge |
| 比較 | <=> | cmp |
Perl 有兩組邏輯運算子,就像比較運算子一樣,但原因不同。
第一組(有時被稱為 C 風格的邏輯運算子,因為它們是從 C 借來的)是&&, ||,和!。它們分別表示邏輯 AND、OR 和 NOT。第二組是and, or,和not.
這兩組之間的唯一區別是它們的優先順序(參見 優先順序)。符號運算子的優先順序遠遠高於文字運算子。
大多數情況下,您將在條件語句中使用邏輯運算子。
# Only prints "I like cookies\n", if both $a is 5 and $b is 2
if ($a == 5 && $b == 2) {
print "I like cookies\n";
}
在這種情況下,您可以安全地替換and為&&,並且條件語句仍將按預期工作。但是,情況並非總是如此。
#True, if $a is 5, and either $b, $c, or both are 2
if ($a == 5 and $b == 2 || $c == 2) {
print "I like cookies\n";
}
#Using brackets, the order is made more clear.
#This conditional acts in the same way as the last.
if ($a == 5 and ($b == 2 || $c == 3)) {
print "I like cookies\n";
}
然而,這完全不同。
if ($a == 5 && $b == 2 or $c == 3) {
print "I like cookies\n";
}
#Equivalent and easier to understand with brackets
if (($a == 5 && $b == 2) or $c == 3) {
print "I like cookies\n";
}
大多數人更喜歡使用 C 風格的邏輯運算子,並使用方括號來強制清晰度,而不是使用文字運算子和 C 風格運算子的組合(如果可能),因為這有時會非常令人困惑。
部分評估(或“短路”)是邏輯運算子的屬性,即只有在需要時才評估第二個表示式。
($a, $b) = (5, 2);
#$b < 3 is not evaluated at all, because when the interpreter
#finds that $a == 4 is false, there is no need to evaluate $b < 3
#because the conditional is automatically false
if ($a == 4 && $b < 3) {
print "I like cookies\n";
}
這也適用於邏輯 OR 語句。如果第一個表示式評估為 true,則第二個表示式永遠不會被評估,因為條件語句會自動變為 true。
這在以下情況中變得有用
sub foo {
#returns a true or false value
}
foo() or print "foo() failed\n";
在這裡,如果foo()子例程返回 false,則列印“foo() 失敗\n”。但是,如果它返回 true,則不會列印“foo() 失敗\n”,因為第二個表示式 (print "foo() 失敗\n") 無需評估。
這些運算子執行與邏輯運算子相同的操作,但不是在整個表示式的 true/false 值上執行,而是在其值的各個對應位上執行。
- &(位 AND)
- |(位 OR)
- ^(位 XOR)
- ~(位 NOT)
左移和右移運算子將左運算元的位(例如,$a << $b 中的 $a)向左或向右移動,移動的次數等於右運算元($b)。每次向左或向右移動有效地將數字減半或加倍,但左移或右移超出位時除外。例如,$number << 3 返回 $number 乘以 8(2**3)。
- <<(左移)
- >>(右移)
字串連線運算子是.,而不是+一些其他語言使用的。
print 'Hello' . ' world'; # prints "Hello world" without a newline at the end
有一個字串重複運算子(x),它將一個字串重複指定次數。
my $str = "hi";
my $repeated_str = $str x 5;
print "$repeated_str\n"; # prints "hihihihihi" with a newline at the end
要比較字串,請使用eqandne代替==or!=分別。您還可以使用substr()查詢子字串,或使用正則表示式進行模式匹配。
範圍運算子 (..) 返回兩個專案之間範圍內的專案列表;這些專案可以是字元或數字。字元的型別由第一個運算元確定;程式碼
print ('A'..'Z');
print ('a'..'z');
print ('A'..'z');
print (1..'a');
print (1..20);
print ('&'..'!');
print (10..-10);
print "$_\n" foreach (1..10);
輸出(為便於閱讀,已新增換行符)
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
1234567891011121314151617181920 &
1 2 3 4 5 6 7 8 9 10
請注意,大小寫由第一個運算元定義,並且1..'a'and(10..-10)操作返回空列表。
任何學習過代數或使用 C/C++ 程式設計的人都會熟悉優先順序這個概念。每個運算子在運算子層次結構中都有自己的位置,並按順序執行。Perl 運算子的優先順序是嚴格的,應使用括號覆蓋,無論是在您有意違反優先順序時還是在您不確定優先順序順序時。有關順序的完整列表,請檢視 perlop。
智慧匹配運算子~~是 Perl 5.10 中的新功能。要使用它,您需要明確說明您正在編寫的是適用於 Perl 5.10 或更高版本的程式碼。它的反向運算子ǃ~智慧地匹配不等式
#!/usr/bin/perl
use strict;
use warnings;
use 5.10.0; # We will be using the smart match operator
my $foo = 'low';
my $scalar = 'hi';
my @array = qw(one two three);
my %hash = (
hi => 1,
ho => 2,
he => 3,
);
if ($scalar ~~ @array) { print "1\n"; } # Doesn't print; 'hi' isn't an element in @array
if ($scalar ~~ %hash) { print "2\n"; } # Does print; 'hi' is a key in %hash
if (@array ~~ %hash) { print "3\n"; } # Doesn't print; none of the elements of @array match a key in %hash
if ($foo !~ %hash) { … }
智慧匹配運算子用途廣泛且速度快(通常比沒有ǃ~or~~的等效比較快)。有關它可以進行的比較,請參閱 智慧匹配的詳細資訊。~~也用於given/when5.10 中的新 switch 語句,這將在其他地方介紹。
先前使用引用運算子引用的變數可以透過使用雙美元符號字首進行解引用
$number = 12;
$refnum = \$number; # backslash is the reference operator
$$refnum = 13; # $$ is used as a dereference to the original variable
$($refnum) = 11; # This is an alternative syntax using brackets
print $number; # the original variable has changed
如果箭頭運算子的左運算元是陣列或雜湊引用,或生成一個的子例程,箭頭運算子將生成元素或雜湊的查詢
$result = $hashreference -> {$key}; # look up a hash key from a reference variable
@arrayslice = $arrayreference -> [3 .. 5]; # obtain a slice from an array reference