1. 列表和数组
关键是理解数组,它的意义和c语言时一样的,不过它更猛,a[0]和a[1]可以存储不同类型的值,帅撒?
1.1 访问数组元素
其实perl访问数组的方法和c语言时一样的,但是它不需要访问之前的那个定义过程,不需要定义类型,不需要定义大小,还要要注意的是如果访问到了没有初始化的数组,返回的可是undef?还记得undef吧
$blank = $fred [142_857] #这样系统时允许的,不过由于该数组元素没有初始化,得到的时undef;
1.2 有趣的索引值
perl里面数组还是有大小的,不过这个大小时动态的,如果你定义了a[88],那么它的大小就是89,如果你直接定义a[10000],那么它的大小就是10001,可以通过$#a来直接得到数组的最后的索引值
所以:a[$#a]即代表最后一个元素,perl中更牛逼的是可以用a[-1]直接得到最后一个元素,同样a[-2]是倒数第二个,如果该数组只有一个元素,用a[-2]则会导致错误,通常我们只用a[-1]取最后一个。
1.3 列表
数组是由括号括起来并且其元素由逗号分隔开的列表。
例子:
(1,2,3)或者(1,2,3,)都代表含有1,2,3的列表
()代表0个元素的空列表
(1 .. 100)#代表1到100的所有整数,这个范围操作符..必须要求两边是整数,否则转换为整数,必须左边小于右边,否则为空列表,而且只能递增1.
1.3.1.Qw简写
(“fefd”,”legend”,”wang”)
实践表明,字符串的列表(如上例)在 Perl 中经常使用。有一种简便的方法可以不用输入大量的引号而达到类似的功能, 那就是使用 qw
qw(ferd legend wang) 注意括号里面时由空格,制表符,换行来分割的,而且分割之后的东西不管里面有什么都是普通的字符,(//)例外,会把它视为(/),而其他所有东西包括(/')都是不转义的,所以现在有个问题,这种方式不能表示带空格的字符串?因为没有能把空格转义的方式。
例子:
@legend = qw {i love china, 'do/ you'};
foreach(@legend)
{
print $_."/n";
}
结果:
legend@ubuntu:~/data/study/perl$ perl 3.4
i
love
china,
'do/
you'
前面两个例子是用括号作为分界符,但 Perl 允许使用任何标点符号作为分界符。下面是一些常用的类型:
qw ! fred barney betty wilma dino !
qw{ fred barney betty wilma dino }
qw[ fred barney betty wilma dino ]
qw< fred barney betty wilma dino >
这些都可以,如果想在内容里加分界符,前面用/来转义就行了
qw! Yahoo/! Google excite lycos ! #其中有个元素是yahoo!
1.4 列表赋值
($fred, $barney, $dino) = (“flintstone”, “ rubble” ,undef);
($fred, $barney) = ($barney, $fred) #交换两个变量的值
如果=左边个数不等于右边个数,如果值多了,就忽略,如果变量多了,就把多的赋值为undef
例子:
@rocks = qw / bedrock slate lava /;
@tiny = (); #空表
@giant = 1..1e5; #包含 100,000 个元素的表
@stuff = (@giant,unfef,@giant); #包含 200,001 个元素的表,注意列表里如果有数组,应该在赋值之前把该数组展开为其值,因为数组变量的值只能是标量,不能是任何变量(参考例子3.4.1)。
@dino = “granite”;
@quarry = (@rocks, “crushed rock” @tiny, $dino); #将五个元素赋给了@quarry,因为@tiny展开是空表,没有东西,千万别以为它是undef。
分析一个经典例子(3.4.2),弄清楚它就相当于弄清楚了undef的真正含义:
@showEmptyArray = ();
@b = ("legend1",@showEmptyArray,"legend2",@showUndefArray,"i think/,you love him",$showUndefBianLiang,"Do you understand?",$showUndefNumber+1);
foreach(@b)
{
print $_."/n";
}
结果:
legend@ubuntu:~/data/study/perl$ perl 3.4.2
legend1
legend2
i think,you love him
Do you understand?
1
看懂了没?重说下undef的含义,如果是变量,其值可能为0或者空串,如果是数组,其值为空表,所以@showEmptyArray和@showUndefArray展开之后都是空串,而$showUndefBianLiang展开之后为空串,自然要占一个元素的位置。而最后一个$showUndefNumber+1展开之后是0+1得1,明白?
@copy = @quarry #复制数组
1.4.1.pop和push操作
@array = 5..9;
$fred = pop(@array); #$fred 得到9,@array 现在为(5,6,7,8)
$barney = pop @array; #$barney gets 8, @array 现在为(5,6,7)
pop @array; #@array 现在为(5,6)(7 被丢弃了)
push(@array,0); #@array 现在为(5,6,0)
push @array,8; #@array 现在为(5,6,0,8)
push @array,1..10; #@array 现在多了10 个元素
@others =qw/9 0 2 1 0 /;
push @array,@others; #@array 现在又多了5 个元素(共有19 个)
1.4.2.shift和unshift操作
@array = qw# dino fred barney #;
$m = shift (@array); #$m 得到“dino”, @array 现在为(“fred”, “barney”)
$n = shift @array; #$n 得到”fred”, @array 现在为(“barney”)
shift @array; #@array 现在为空
$o = shift @array; #$o 得到undef, @arry 仍为空
unshift(@array,5); #@array 现在为(5)
unshift @array,4; #@array 现在为(4,5)
@others = 1..3;
unshift @array, @others; #array 现在为(1,2,3,4,5)
1.5 将数组插入字符串
@rocks = qw{ flintstone slate rubble };
print “quartz @rocks limestone/n”; #输出为5 种rocks 由空格分开,其中@rocks的三个元素之间用空格隔开,而首位两个前后都没有空格
$email =“fred@bedrock.edu”; #错误!将会替换@bedrock
$email =“fred/@bedrock.edu”; #正确
$email =‘fred@bedrock.edu’; #另一种方法
注意如果数组变量和标量变量同名,引用时数组变量优先
@fred = qw(eating rocks is wrong);
$fred = “right”; #我们将打印“this is right[3]”
print “this is $fred[3]/n”; #打印出“wrong”使用$fred[3]
print “this is ${fred}[3]/n”; #打印出“right”(由花括号分开)
print “this is $fred”. “[3]/n”; #正确(两个字符串,右. 分开)
print “this is $fred/[3]/n”; #正确(利用反斜线转义)
1.6 foreach控制语句
foreach $rock (qw/ bedrock slate lava /){
print “One rock is $rock./n”; #打印出3 种rocks
}
领会下面的例子:
#!/usr/bin/perl
@rocks = qw /legend1 legend2 legend3/;
print @rocks;
print "over/n";
foreach $rock(@rocks)
{
$rock = "/t".$rock;
$rock .="/n";
}
print "the rocks are:/n",@rocks;
结果:
legend@ubuntu:~/data/study/perl$ perl 3.6
legend1legend2legend3over
the rocks are:
legend1
legend2
legend3
该例说明了两件事:
1,控制变量不是这些列表元素中的一个拷贝而是这些元素本身。也就是说,如果在循环中修改这个变量,那原始列表中的元素也会被修改
2当循环结束时$rock 的值为多少呢?其值同循环开始之前相同。foreach 循环中控制变量的值会被Perl 自动保存和恢复。当循环进行时,是没有办法改变其值的。循环结束时,变量的值会回到循环开始前,如果没有值则为undef。这意味着如果有一个变量和控制变量有相同的名字:“$rock”,不用担心会混淆它们。
1.6.1.默认变量$_
foreach(1..10){ #使用默认的变量$_,直接省略了控制变量
print “I can count to $_!/n”;
}
$_ =“Yabba dabba doo/n”;
print; #打印出默认变量$_。
1.6.2.Reverse逆转列表或者数组再返回,但是传入的数组没有变化
@fred = 6 ..10;
@barney = reverse (@fred); #得到10,9,8,7,6
@wilma = reverse 6 ..10; #同上,没有使用额外的数组
@fred = reverse @fred; #将逆转过的字符串存回去
1.6.3.Sort排序,无论数字还是字符,都按ASC序排,通常数字这样排序没有意义
@rocks = qw/ bedrock slate rubble granite /;
@sorted = sort(@rocks); #得到bedrock, granite, rubble, slate
@back = reverse sort @rocks; #为slate 到bedrock
@rocks = sort @rocks; #将排序的值写回@rocks
@numbers = sort 97 ..102; #得到100,101,102,97,98,99
和reverse是一样的,也不改变传入参数的值
1.7 标量和列表上下文
@people = qw( fred barney betty );
@sorted = sort @people; #列表context:barney , betty, fred
$number = 42 + @people; #标量context:42+3,得到45
@list = @people; #3 个People 的列表
$n = @people ; #数字3
1.7.1.在标量Context 中使用List-Producing 表达式
@backwards = reverse qw / yabba dabba doo /;
#返回doo, dabba, yabba
$backwards = reverse qw/ yabba dabba doo /;
#返回oodabbadabbay
如果你见到神人写出
$backwards = sort qw/ yabba dabba doo /;
那么其实$backwards 为undef
例子3.7.1:
#!/usr/bin/perl
$a = reverse qw /legend1 legend2 legend3/;
print $a."/n";
$b = qw /legend1 legend2 legend3/; #对标量进行赋值,取列表的最后一个元素
print $b."/n";
($c) = qw /legend1 legend2 legend3/; #对列表进行赋值
print $c."/n";
结果:
legend@ubuntu:~/data/study/perl$ perl 3.7.1
3dnegel2dnegel1dnegel
legend3
legend1
1.7.2.在列表Context 中使用Scalar-Producing 表达式
仔细品味下面的例子:
#!/usr/bin/perl
@a = undef; #将undef赋值了,所以@a为有一个元素的列表
$aNum = @a; #上下文环境为标量,所以值为1
print $aNum."/n";
print "the /@a is:",@a,"over","/n"; #上下文环境是列表,所以显示为列表的undef值空串
print "the /@a is:".@a."over"."/n"; #标量环境,为1
@b = (); #空串赋值,所以@b没有元素
$bNum = @b; #上下文环境为标量,所以值为0
print $bNum."/n";
print "the /@b is:",@b,"over","/n";
print "the /@b is:".@b."over","/n";
结果:
legend@ubuntu:~/data/study/perl$ perl 3.7.2
1
the @a is:over
the @a is:1over
0
the @b is:over
the @b is:0over
1.7.3.强制转换为标量Context 在列表前面加上scalar
@rocks = qw(talc quartz jade obsidian);
print “How many rocks do you have?/n”;
print “I have ”, @rocks, “rocks!/n”; #错误,输出rocks 的名字
print “I have ”, scalar @rocks, “rocks!/n”; #正确,输出其数字
1.8 <STDIN>在列表Context 中
@lines = <STDIN>; #将输入读入列表context 中,每行一个元素
如果是这样,你按完换行就是对下一个元素的输入,什么时候是个头呢,linux一般用ctrl+D结束。
常用用法:chomp (@lines = <STDIN>); #读入所有的行,不包括换行符,因为chomp能将每个元素最后的那个换行符去掉再赋值给相应元素。