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()查找子字符串,或使用正则表达式进行模式匹配。
- 请参阅 Perl 编程/函数参考#-X
范围运算符 (..) 返回两个项目之间范围内的项目列表;这些项目可以是字符或数字。字符的类型由第一个操作数确定;代码
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