列表指的是标量的有序集合,而数组则是存储列表的变量;精确的说,列表指的是数据,数组指的是变量。
访问数组中的元素
数组元素是以连续的整数来编号,从0开始,之后的每一个元素依次加1,例如
$fred[0] = "yabba"; $fred[1] = "abba"; $fred[2] = "doo";
数组的名字空间和变量的名字空间是完全分开的,因此可以在同一个程序里再取一个名为$fred的变量而不会冲突。
任何求值能得到数字的表达式都可以作为下标。如果它不是整数,则会自动舍去小数,无论正负。
特殊的数组索引
例如,对于上例中的数组@fred,最后一个元素的索引值是$#fred。
不过Perl为此类用法提供的更为简洁的“负数数组索引值”。上例中,$fred[-1]="doo", $fred[-2] = "abba"……
列表直接量
列表直接量由圆括号隔开的一串数据表示,这些数据就称为列表元素。例如
(1, 2, 3) #包含1、2、3这三个数字的列表 (1..100) #100个整数构成的列表
注意,范围操作符".."会从左边的数字计数到右边,每次加1;但是范围操作符只能向上计数,如果需要一个倒序的列表,可以使用reverse 操作符。
在Perl程序里,经常需要建立简单的单词列表,这时只需要使用qw简写,就可以省去键入无谓引号的麻烦,例如:
qw( fred barney betty wilma dino ) 或者 qw# #看起来像注释,不过这里用作定界符,此外还可以用!、/、[]、{}等任何标点符号作为定界符 fred #可以使每个元素独立成行,便于阅读和修改 barney betty wilma dino #
常用的数组操作符
pop和push操作符,pop负责取出数组中的最后一个元素并将其返回,push将一个或多个元素添加到数组的尾端,例如
@array = 5..9; $fred = pop @array #$fred变成9,@array变成(5, 6, 7, 8) push @array, 9 #@array变成(5..9)
shift和unshift操作符同上面的完全相反,处理数组开头的部分,例如
@array = qw # dino fred barney #; $m = shift(@array); # $m变成"dino", @array变成("fred", "barney") $n = unshift(@array, "betty"); # @array变成("betty", "fred", "barney")
splice操作符用于操作数组中间的的某些元素,它可以接受至少两个,最多四个参数,例如:
@array = qw( pebbles dino fred barney betty ) @removed = splice @array, 3 # 删掉元素barney及其以后元素,@removed变成qw ( barney betty ) @array = qw( pebbles dino fred barney betty ) @removed = splice @array, 1, 2 # 从索引1开始,删掉2个元素,@array变成qw( pebbles barney betty ),@removed变成qw( dino fred ) @array = qw( pebbles dino fred barney betty ) @removed = splice @array, 1, 2, qw( wilma ) # @array变成qw( pebbles wilma barney betty ),@removed变成qw( dino fred )
reverse操作符
@fred = 6..10; @barney = reverse @fred; # 得 10, 9, 8, 7, 6
必须注意,reverse不会修改传进来的参数,只会返回次序相反的列表。
sort操作符
sort操作符会读取列表的值,而且会根据ASCII码的大小对它们进行排序。
@fred = 8..12; @rocks = sorts @fred # 得到10, 11, 12, 8, 9
each操作符
Perl 5.12版引入了each操作符,用于返回数组中下一个元素所对应的索引和值。
use 5.012; my @rocks = qw / bedrock slate rubble granite /; while (my($index, $value) = each @rocks) { say "$index: $value"; }
foreach控制结构
foreach能逐项遍历列表中的值。控制变量不是列表元素的复制品,它就是列表元素本身。(我想Perl内部应该是用指向列表的指针实现的控制变量)
加入在foreach循环开头省略控制变量,Perl就会用它最喜欢的默认变量"$_",在许多情况下,当未告知Perl使用哪个变量或数值时,Perl都会自动使用"$_"。
标量上下文与列表上下文
如同自然语言,Perl的同一个表达式出现在不同的地方会有不用的意义。
对于数组来说,在列表上下文中,它会返回元素的列表;在标量上下文中,则返回数组中元素的个数:
@people = qw (fred barney betty) @sorted = sort @people # 列表上下文:barney, betty, fred $number = 42 + @people # 标量上下文:42 + 3 = 45
当然,并不是一定会在标量上下文中得到列表的个数。比如sort在标量上下文中会返回undef。(实际上没人需要统计列表排序后的元素个数)
reverse是一个更加有趣的例子:
@backwords = reverse qw/ yabba dabba doo /; #会得到 doo,dabba,yabba $backwords = reverse qw/ yabba dabba doo /; #会得到oodabbadabbay
相对于上面的用法,在列表上下文中使用产生标量的表达式就简单很多了:如果表达式求值结果为标量值,则自动产生一个仅含此标量值的列表。
@fred = 6 * 7; # 得到仅有一个元素的列表(42)
强制指定标量的上下文
可以使用伪函数"scalar"从列表上下文切换到标量上下文:
@rocks = qw( talc quartz jade obsidian ); print "I have", scalar @rocks, "rocks!\n"; #打印出的是石头的种数
列表上下文中的
在标量上下文中,
当输入数据来自某个文件时,列表上下文会读取文件的剩余部分。如果是键盘输入:Unix或类似系统可以键入"Control+D"来告知系统不会有任何输入了;对于Windows来说,需要使用"Control+Z"。