清新的Perl(四)——数组以及jion函数
在数组学习方面,包含了四个要点:
- 数组如何赋值,包括把数字、字符和标量赋值给数组。
- 数组赋值后如何添加或删除新的元素。
- 获取数组长度以及用for、foreach如何遍历数组。
- 用join函数将数组变为字符串。
一 为什么用数组这种存储结构?
我们为什么需要数组这种存储结构呢?实际上,很多编程语言会把数组称作列表。列表引申为表格,在生活、工作中,我们处处需要表格——家里的账本、工作中天天处理的excel表格都是。表格,使我们需要的信息整齐、清晰、方便的展示出来,易懂又容易计算、整理。
同样,计算机对列表也是情有独钟的。我们之所以会使用计算机,原因在于计算机可以批量处理大量的数据,方便省时。而这种计算魅力源于“数组”、“判断”以及“循环”。
数组是循环结构的基础。无论哪种编程语言,想要用循环,就离不开数组的使用。
二 数组赋值及增删操作
数组赋值,前面讲了,网络上也有各种教程,就不多讲了。下面主要讲讲数组赋值后的增删操作,主要涉及四个函数,push、pop、shift、unshift。
嗯……先说下这四个函数能干什么。push和unshift两个函数都是往数组中添加元素,push往末尾添加(假设数组末尾标号为n,那么新元素就是a[n]),unshift往开头添加(新元素就是a[0])。pop和shift两个函数都是从数组中取值,pop从末尾取值,shift从开头取值。
实际上Perl中数组涉及到的函数,远不止这四个,更高级点的函数还有map函数(许多高级实践中经常会使用,但作为初学者来说,map函数实际上是对数组循环结构的一种简化)。
根据数组的实际使用场景,最常用到的是push和pop两个函数。在循环结构中,我们向数组中添加数据,我们会经常用到push。看个例子:
@array = ("苹果","梨","香蕉");
$a = "菠萝";
push @array,$a; #数组结果为"苹果","梨","香蕉","菠萝"
pop,虽说是第二常用的方法,但是实际使用场景并不多。大部分场景下,我们仅仅是需要遍历数组中的值,而不需要把值删除。根据我的个人经验,pop主要用在查找复杂目录结构时简化程序结构,比方说列出电脑C盘内所有文件的名称:

就像上面的示意图一样,我们很难预估C盘到底有多少层文件夹,每个文件夹中又有几个文件夹需要打开进行查找。这种时候,我们需要用一个数组作为待查找文件夹的存放池(@temp)。当我们打开C盘根目录时,一方面把每个文件的名称用push方法存储到一个数组中;另一方面,把所有的文件夹用push方法放入temp数组。之后,用pop方法从temp数组中取出文件夹,重复上面的操作。不断的循环处理,当检查到temp数组为空(没有任何值)时,我们就可以结束循环,打印存放文件名称的数组,完成C盘所有文件夹的查找了。
#!/usr/bin/perl
#编写此例时,查找文件夹中子文件夹和文件,我使用了glob函数
#glob函数可以返回目录中所有子项的绝对路径
#注意glob的参数字符串末尾要加“/*”
use strict; #使用strict模式,可以规范书写格式
my $dir = 'C:/*'; #要遍历的目录
my @temp;
my @all_files;
find_file($dir); #函数,原型在末尾
while(1){ #循环结构,用于遍历所有的子文件夹
my $file = pop @temp;
last if not $file; #如果temp数组中没有元素,就结束循环
find_file($file);
}
foreach (@all_files){ #打印所有的文件
print $_."\n";
}
sub find_file{
my $dir = shift; #参数项
my @files = glob( $dir ); #glob函数返回值为文件夹和文件绝对路径组成的列表
foreach my $file (@files ){ #遍历列表中的每一项
my @files1 = glob($file.'/*'); #通过glob函数,如果是文件夹
#那么将返回一个列表,如果是
#文件将返回一个空值
if (@files1) {
foreach my $file1 (@files1){
push @temp,$file1;
}
} else {
push @all_files,$file; #如果列表为空值,证明是文件,放入文件存储列表中
}
}
}
三 数组长度和for、foreach循环遍历
文章开篇提到数组是循环的基础,现在我们该来讲讲循环。正如上面一个例子中,我用到了while和foreach两种循环结构。作为本系列文章的主旨——“清新”,我们力求将perl最常用的、最简单的知识呈现在初学者面前,使大家能够快速入门perl语言。在这里,我要划重点,循环结构最常用到的for(foreach)和while,只此两种。
1.老旧的、不常用的for结构和数组长度:
这里指的是类似C语言的for结构。先搬一个例子过来:
#!/usr/bin/perl
# 执行 for 循环
for( $a = 0; $a < 10; $a = $a + 1 ){
print "a 的值为: $a\n";
}
如果我们需要用这种结构遍历一个数组呢?我们需要先知道数组的长度:
#在perl语言中,数组长度通常使用如下方法获取
@array=(1,2,3,4,5,6);
print $#array;
#在数组名字array前面加$#表示返回数组最后一个元素的下标
#那么数组长度就是该值加1:
$len = $#array+1
下面,我们就可以遍历数组了:
for( $a = 0; $a < $#array+1; $a = $a + 1 ){
print "array数组中下标$a 的值为: $array[$a]\n";
}
2.常用的for(foreach)
实际应用中,上面这种for结构基本用不到。一般用这种,用久了甚至会忘记前面这种写法……
抄抄前一节中列子:
foreach $file1 (@files1){
push @temp,$file1;
}
#foreach 标量 (被遍历的数组){
# 使用标量……
#}
在这种写法中,foreach可以简写为for,这就是为什么叫做for常用结构。
3.while结构
while(1){ #循环结构,用于遍历所有的子文件夹
my $file = pop @temp;
last if not $file; #如果temp数组中没有元素,就结束循环
find_file($file);
}
while循环结构,一般括号内为循环条件,即while(condition){……}——符合条件便执行循环,不符合就退出循环执行下面的代码。
在程序设计时,我们经常会不确定何时结束循环。此时常用的结构就是while(while(1))死循环+循环控制关键字(next和last)。正如此例中,我们用到了last关键字,意思是当temp数组中没有元素时结束循环。而next关键字的意思是结束本次循环,不在执行{}内next后面的语句,进入下一次循环。
四 join函数
正如我们需要将标量字符串用split函数分割为数组一样,我们也常常需要将数组连接为标量字符串。
#!/usr/bin/perl
# 定义字符串
$var_string = "www-runoob-com";
$var_names = "google,taobao,runoob,weibo";
# 字符串转为数组
@string = split('-', $var_string);
@names = split(',', $var_names);
# 数组转为字符串
$string1 = join( '-', @string );
$string2 = join( ',', @names );
print "$string1\n";
print "$string2\n";
下一篇,我将讲解perl散列的常用要点。