Learning Perl
第三章 列表和数组
Perl的标量代表单数(signal),代表复数(plural)的就是数组和列表。
列表指的是标量的有序集合,数组则是存储列表的变量。
列表指的是数据,数组指的是变量。
数组或列表中的每个元素都是单独的标量变量,拥有独立的标量值。这些值是有序的,索引从0开始。
数组和列表可以包含任意多个元素。
通过数组下标,访问数组中的元素。
数组的长度是没有上限的,如果需要增补元素,那么默认取值为undef。
最后一个元素的索引为$#rocks。
从数组尾端往回计数的负数数组索引值。
列表直接量
列表直接量(list literal),有圆括号内的逗号隔开的一串数据表示,这些数据就是列表元素。
列表可以包含任意标量值:
("caoqing", "xiaohuan", "xiaobao")
..范围操作符。
(1..10)
qw
需要建立简单的单词列表,可以省去键入引号的麻烦:
qw(caoqing, xiaohuan, xiaobao)
qw表示"quoted word",Perl都当其为单引号内的字符串来处理。空白符会被迫弃,剩下的就是列表的元素。
前面的例子是一圆括号作为定界符(delimiter)。Perl允许用任何标点符号作为定界符。
qw ! caoqing xiaohuan xiaobao !
qw / caoqing xiaohuan xiaobao /
被圈引的字符串内无法使用定界符,可以通过反斜线转义字符。
列表的赋值
($caoqing, $xiaohuan, $xiaobao) = ("caoqing", "xiaohuan", "xiaobao");
当希望引进整个数组,需要在数组名前加上@字符
@rocks = qw / caoqing xiaobao xiaohuan /;
@giant = 1..1e5;
@stuff = (@rocks, undef, @giant);
数组名会被展开成元素列表,数组只包含标量,不包含其他数组,所以数组无法成为列表里的元素。
将数组进行复制时,仍是列表的赋值运算。
@copy = @quarry;
pop和push操作符
要新增元素到数组尾端时,只要将它存放在更高索引对应的新位置。
常把数组当成堆栈(stack)。
pop操作符,负责取出数组中最后一个元素并将其作为返回值返回。
@array = 1..10;
$caoqing = pop(@array);
$xiaohuan = pop(@array);
print "$caoqing, $xiaohuan";
10, 9
如果数组为空,pop返回undef。
push操作符,用于添加一个元素到数组的尾端。
push或者pop的唯一参数都是要操作的数组变量。
@array = 1..10;
push(@array, 11);
push(@array, 1..10);
@other = qw / 3, 5, 6, 2 /;
push @array, @others;
shift和unshift操作符
对应数组的左边进行相应的处理。
splice操作符
push-pop,shift-unshift操作符都是针对数组首位端操作的,splice操作符可以添加或者移除中间的元素。
最多接受四个参数,最后两个是可选参数。第一个参数是要操作的目标数组,第二个是操作的一组元素的开始位置。
@array = qw (cao qing wang huan xiao bao);
@removed = splice(@array, 3);
第三个参数指定要操作的元素长度,第四个参数是要替换的列表。
@array = qw (cao qing wang huan xiao bao);
@removed = splice(@array, 1,2,qw(pig));
字符串中的数组内插
和标量一样,数组的内容同样可以被内插到双引号串中。内插时,会自动添加分割用空格:
@rock = qw {caoqing xiaohuan xiaobao};
print "pig @rock dog\n";
pig caoqing xiaohuan xiaobao dog
数组内插时,首位都不会增加额外的空格;
数组内插时,在处理电子邮件时会有问题,要规避这种问题,需要将@转义,或者直接用单引号来定义字符串:
$email = "caoqing\@gmail.com";
$email = 'caoqing@gmail.com';
内插数组中的某个元素时,会被替换成该元素的值。
索引表达式会被当成普通字符串表达式处理。
如果要在某个标量变量后面直接写左方括号,需要先将这个方括号隔开,才不会被识别为数组引用的一部分。
@fred = qw (caoqing love xiao bao);
$fred = "xiaohuan";
print "This is $fred[3]\n";
print "This is ${fred}[3]\n";
print "This is $fred"."[3]\n";
print "This is $fred\[3\]\n";
This is bao
This is xiaohuan[3]
This is xiaohuan[3]
This is xiaohuan[3]
foreach控制结构
如果对整个列表和数组进行处理非常方便,Perl提供另一种控制结构。
foreach(循环)中能逐项遍历列表中的值,一次迭代:
foreach $i (qw {caoqing xiaohuan xiaobao}){
print "One name is $i.\n";
}
One name is caoqing.
One name is xiaohuan.
One name is xiaobao.
存储的变量在foreach循环变量循环结束后还原,不必担心前面是否用过同名的变量。
Perl内置变量:$_
foreach循环开头省略控制变量,Perl使用默认变量:$_。
foreach (qw {caoqing xiaohuan xiao bao}){
print "One name is $_.\n";
}
One name is caoqing.
One name is xiaohuan.
One name is xiao.
One name is bao.
reverse操作符
reverse操作符会读取列表的值,并按照相反的顺序返回该列表。
@cao = (1..10);
@qing = reverse(@cao);
Perl会先计算等号右边要赋的值,在实际进行操作。
reverse会返回次序相反的列表,并不会修改传进来的参数。
sort操作符
sort操作符会读取列表的值,而根据内部字符编码顺序进行排序。大的字符排列在前面,数组在字母前,标点散落各处。
sort操作符的参数应该是某个输入列表,然后进行排序,继而返回排序后的列表。
@rock = qw (caoqing xiaohuan xiao bao);
@sorted = sort(@rock);
foreach (@sorted) {
print "$_\t";
}
bao caoqing xiao xiaohuan
each操作符
Perl5.12开始,可以针对数组使用each操作。之前只能用于提取哈希的键值对。
对数组调用each,会返回该元素的索引和该元素的值:
@rock = qw (caoqing xiaohuan xiao bao);
while(my ($index, $value) = each(@rock)) {
print "$index : $value\n";
}
0 : caoqing
1 : xiaohuan
2 : xiao
3 : bao
如果不是用each实现,可以根据索引进行遍历,然后借助索引值取得元素值:
my @rock = qw (caoqing xiaohuan xiao bao);
foreach $index (0..$#rock) {
print "$index : $rock[$index]";
}
0 : caoqing1 : xiaohuan2 : xiao3 : bao
标量上下文和列表上下文
同一个表达式出现在不同的位置会有不同的意义。
所谓上下文,指的是如何使用表达式。
Perl解析表达式时,要么返回标量,要么返回列表。
42 + some
sort some
some这个单词在某种情况下得到单一的标量值,而在另外情况下得到一个列表。Perl总是根据需要的上下文返回对应的值。
数组名称为例,在列表上下文,返回元素的列表;在标量上下文,返回数组中元素的个数:
@animal = qw (dog cat pig);
@sorted = sort @animal;
$number = 42 + @animal;
print "$number";
45
在标量上下文中使用产生列表的表达式
某些表达式不会在标量上下文中返回任何值。
一些常见的上下文:
$fred = something; #标量上下文
@animal = something; #列表上下文
($cao, $qing) = something; #列表上下文
($bao) = something; #列表上下文
如果给列表或者数组赋值,就是列表上下文。
标量上下文:
$fred = something;
$fred[3] = something;
123 + something;
if (something) {...};
while (something) {...};
$fred[somthing] = something;
列表上下文:
@fred = something;
($fred, $cao) = something;
($cao) = something;
push @fred, something;
foreach $fred (something) {...};
sort something;
reverse something;
print something;
在列表上下文使用产生标量的表达式
@fred = 6 * 7;
@qing = "hello" . '' . "world";
强制指定标量上下文
Perl要在列表上下文的地方强制使用标量上下文,可以使用伪函数scalar。
@rocks = qw / cao qing wang huan /;
print "How many rocks do you have?\n";
print "I have ", scalar rocks, "rocks.\n";
习题
1. 写一个程序,读入一些字符串,直到文件结尾为止。然后,按照相反顺序输出这个列表。
2. 写一个程序,读入一些数字,然后根据数字输出如下名单中相应的人名。
cao qing wang huan xiao bao
3. 写一个程序,读入一些字符串,然后按照ASCII码顺序输出所有字符串。
答案:
1.
print "Please enter some lines, then press Ctrl-D:\n";
print reverse <STDIN>;
2.
@name = qw( cao qing wang huan xiao bao );
print "Enter some numbers from 1 to 6, one per line, then press Ctrl-D:\n";
chomp(@numbers = <STDIN>);
foreach (@numbers) {
print "$name[$_ - 1]\n";
}
3.
chomp(@lines = <STDIN>);
@sorted = sort @lines;
print "sortedz\n";
转载于:https://my.oschina.net/u/1449160/blog/203967