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";