1.5 操作符 BACKWARDFORWARD


就象我们前面提到的, Perl也是一种数学语言。这在多个级别上确实是这样的,从低级二值逻辑操作,到数字和集合的操作,到较大的各种类型的生 明和抽象。象我们从学校学习数学知道,数学家喜 欢奇怪的符号。遭糕的是,计算机科学家已使用这 些奇怪符号。Perl也有这些奇怪的符号, 但放心, 大多数是借自C语言,FORTRAN, sed(1)或awk(1), 所 以他们对那些语言的用户是熟悉的。

Perl的嵌入操作按着数字操作项分为一元的, 二元 的, 和三元的操作符。他们也 可按着是否是前缀 或后缀操作符来分类。他们也可按着他们操作对象 的种类分类,例如,数字,字符串或文件。后面, 我们将给你所有操作的一个表,这儿只是开始。


1.5.1 算术操作符

算术操作符完成学校中你所学习的操作。他们对数 进行各类数学函数的操作。


表1-2:一些二元算术操作符


例子      名字     结果

$a + $b     加     $a与$b的和

$a * $b     乘     $a与$b的乘积

$a % $b     模除    $a除$b的余数

$a ** $b     指数    $a的$b幂指数

是的, 我们省略了减法和除法。但我们认为你能想 出他们将如何计算的。试一试,看你是否对了。算 术操作符按着你的数学老师教你的顺序(即, 指数优 先于乘法, 乘法优先于加法)进行计算。你能使用括 号使计算顺序不同。


1.5.2 字符串操作符

对于字符串也有一个"加"操作符, 完成联结操作。 不象一些语言和算术加混合,Perl给串联结定义一 个单独的操作(.) :

$a = 123;

$b = 456;

print $a + $b; #打印579

print $a . $b; #打印123456

对于字符串也有一个"乘"操作, 也被称为重复 (repeat)操作。为和数字乘区别,它也是一个单独 的操作符(x):

$a = 123;

$b = 3;

print $a * $b; #打印369

print $a x $b; #打印123123123

这些字符操作符和相应的算术操作符紧密相联。这 个重复操作是不寻常的, 它左边的参数是一个字符 串, 但右边的参数是一个数字。注意Perl是怎样自 动地把数字转为字符串。你把上面的字母数字放入 括号中,它也仍能产生同样的输出。尽管在内部, 它已按着相反顺序被转为(即, 从字符串到数字)。

还有几个问题要考虑。串联结也由双引号字符串的 插入隐含。当你打印一个表时,你也有效地联结字 符串。所以下面语句产生同样的输出:

print $a. ' is equal to ' . $b . ""; #. 操作

print $a,' is equal to ', $b, ""; # 表

print "$a is equal to $b"; # 插入

这些你使用哪一个完全由你决定。

开始看时,x操作似乎相对有价值, 但有时是相当有 用的, 特别对于下面:

print "-" x $scrwid, "";

假设你的屏幕长为$scrwid, 这将在你的屏幕上产生 一行。


1.5.3 赋值操作符

虽然不恰巧是一个数学操作符, 但我们也对简单赋 值操作(=)的使用进行了扩展。记住=的意思是"设为 "而不是"等于"。(也有一个数学相等操作符==, 意 思是"等价", 如果你现在考虑他们之间的区别, 那 么以后你将省去许多头痛的事。)

象上面的操作一样, 赋值操作符是二元中缀操作符, 意思是他们有两个操作项, 分别在操作符的两边。 右边的操作项能是任何表达式,但左边的操作项必须是一个有效的左值(即, 象一个变量的一个有效的存储位置, 或数组中的一个位置)。最一般的赋值操 作是简单的赋值。计算右边表达式的值,并把这个 值赋给左边的变量:

$a = $b;

$a = $b + 5;

$a = $a * 3;

注意最后一个赋值对同一个变量操作两次; 一次用 于计算, 一次用于赋值。没有麻烦,但这是一般的 操作,对于这个有一种缩写(来自于C语言)。如果你 写:

lvalue operator = expression

按下面表达式进行计算:

lvalue = lvalue operator expression

除了左值不能被计算两次。

所以, 例如, 你能象这样写:

$a *= 3;

这是计算"$a乘3"。你能用Perl中几乎任何二元操作 符完成这个, 甚至一些C语言中不能这样做的:

$line .= ""; #给$line后加一个换行符。

$fill x= 80; #使串$fill重复本身80次。

$val ||= "2" #如果$val没有设置, 则设为 2。

我们的班级例子的第六行包含两个串联结,其中之 一是一个赋值操作。并且第14行包含+= 。

无论你使用哪类赋值操作符,最后的值被返回作为 整个赋值语句的值。(这不象在Pascal中赋值是一个 语句并没有值)。这就是我们为什么能写:

chop($number = <STDIN>);

并删去$number的最后一个值。你也经常频繁地看到 赋值语句作为while循环的条件,就象班级例子中的 4行。


1.5.4 自动增1和自动减1操作符

象$variable +=1 不是足够简炼的, Perl有来自C语 言的一种更简炼的方法给一个变量增1。自动增1和 自动减1操作符简单地给变量加1(或减1)。操作符可 以放在变量的任何一边,根据你要求的计算。


表1-3: 一元算术操作符


例子     名字     结果

++$a, $a++  自动增1    给$a加1

--$a, $a--  自动减1    给$a减1

如果你把操作符放在变量的前面, 则先增(先减)变 量。变量的值在引用以前将被改变。如果操作符放 在变量的后面,则后增(后减)变量并且变量值在使 用后改变。例如,

$a = 5; #$a被赋为5

$b = ++$a; #$a增1为6, 并赋给$b

$c = $a--; #$c被赋为6, 然后$a减1, 结果 为5

班级例子第15行, 给score的数增1, 所以我们知道 我们正计算多少个成绩。这儿使用的是后增操作 ($scores++), 但这种情况没有关系, 因为这个表达 式在不确定的上下文, 计算这个表达式就是为了给 这个变量增1[1]。   


1.5.5 逻辑操作符

逻辑操作符也作为"简洁"操作符, 允许程序根据几个标准判断结果, 而不使用嵌套的条件。他们被称为简洁操作是因为:如果计算左边参数足够确定整 个值,那么就不计算右边参数的值。

Perl有两类逻辑操作, 一类是来自于C语言旧的表示法, 另一种是新的易于读的操作(一旦进行计算时, 他们是同样的作用)。


表1-4: 逻辑操作符


例子    名字     结果

$a && $b  与      如果$a是真的, 并且$b也是真的, 则为真

! $a    非      如果$a不是真的, 则为真

$a and $b 与      如果$a是真的, 并且$b也是真的, 则为真

$a or $b  或      如果$a是真的, 则$a, 否则为$b

not $a   非      如果$a不是真的, 则为真

因为逻辑操作符的简洁的方法, 所以他们经常用于有条件的执行代码。下面一行(是班级例子中的)想 要打开文件"grades"。如果能打开这个文件,它将 执行程序的下一行。如果不能打开这个文件,它将 给我们一个错误提示并停止执行。

open(GRADES, "grades") or die "Can't open file grades; $!";

语义上是, "打开grades, 否则die !"。(变量$!保留操作系统返回的错误提示)当然, 这些逻辑操作也能用在传统的条件结构中, 例如, if和while语句。


1.5.6 比较操作符

比较, 或关系的, 操作告诉我们两个标量值相互之 间怎样联系。有两类操作符,一种是数字比较,另 一种是字符串比较。(两种情况, 参数首先将被强制 为一致的)下表中设$a和$b分别为左参数和右参数。


表 1-5: 数字的和字符串的操作符


比较     数字     字符串    返回值

相等     ==      eq      如果$a和$b相等, 则为真

不等     !       ne      如果$a和$b不等, 则为真

小于     <       lt      如果$a小于$b, 则为真

大于     >      gt      如果$a大于$b, 则为真

小于或等于  <=      le      如果$a不大于$b, 则为真

比较     <>      cmp     如果$a等于$b则返回0, 如果$a大于$b则                     返回1,如 果$a小于$b则返回-1

你可能想到最后的一对操作(<=>和cmp)完全是冗余的。如果这样,你是对的。但他们在sort子程序中 是不可缺少的[2]。   


1.5.7 文件检测操作符

在你进行处理以前, 文件检测操作符允许你检测某 个文件属性是否被设置。例如,在你处理和打开 /etc/passwd文件作为新文件以前,这是最好的方法了解该文件是否已存在。


表1-6: 一些文件检测操作符


例子     名字     结果

-e $a    存在     如果以$a命名的文件存在, 则为真

-r $a     可读的    如果以$a命名的文件是可读的, 则为真

-w $a     可写的    如果以$a命名的文件是可写的, 则为真

-d $a    目录     如果以$a命名的文件是一个目录, 则为真

-f $a     文件     如果以$a命名的文件是一个规则的文件, 则为真

-T $a    文本文件   如果以$a命名的文件是一个文本文件, 则为真


这儿有一些例子:

-e "/usr/bin/perl" or warn "Perl is improperly installed";

-f "/vmunix" and print "congrats, we seem to be running BSD Unix";

注意: 一个规则的文件与一个文本文件不是同的。象/vmunix的二进制文件是规则的文件, 但不是文本文件。文本文件是和二进制文件相对反的,而规则文件是与“不规则”文件,象目录和设备,相反的。有很多文件检测操作符,我们没有列出这么多。多数文件检测是一元布尔操作符:他们只有一个操作 项,是一个文件或一个文件句柄的一个标量,并且返回一个真或假。他们中很少返回其他数,象文件的大小或场长度,但当你需要时,你能查到他们。


Copyright: NPACT BACKWARDFORWARD