Perl无废话入门指南

最近接到一个任务是这样的,一台 Solaris 服务器上需要运行一个脚本,每天统计 MySQL 数据库中的数据并生成报表。本来这是一个可以就事论事的小项目,但是为了以后的灵活和可扩展性,我设计了一个使用 XML 做统计模版配置的方案。由于在 Bash 下不太好实现 XML 的访问,因此我考虑用 Perl 来实现这个脚本。

Perl 是一个强大的脚本语言,本来是设计应用在文本处理方面的,但是后来发展的越来越强大,已经可以处理网络、图形、系统、文件等等各个方面的内容。 Perl 本身内置了丰富的操作符和函数,外部也有多年积累下来的大量模块。但是不知道什么原因在国内好像很少有人用。关于 Perl 的历史我就不多说了,有兴趣可以上网查一下。有一点要说的是,目前 Perl 最新的版本是 5.8.6 ,而 Perl6 虽然已经设计很久了但是由于自举问题目前还没有一个可用的版本。为了解决这个问题,台湾的唐宗汉发起的 Pugs 项目正在快速的实施中,可能很快就能有结果了,有兴趣的朋友可以多多关注一下,也许还可以为开源世界做点贡献。

虽然很早以前就了解过 Perl ,但是从来就没有实际的用它做过项目,因此这次的实现是一个边学边做的过程。作为一个程序员,学习一种新的语言总会有一点惯性思维,加之 Perl 在语法上与 C 语言比较类似。因此我想在这片文章中主要以 C 为背景做一个比较。这种比较不是比较语言上的优劣,而是说明同样的功能如何在 Perl 中实现以及之间的区别。限于篇幅,具体的技术实现的细节我就不在这里多说了,你可以在末尾的资源一节中找到很多相关的文章。如果你没有接触过 Perl ,我想你可能更希望看到学习 Perl 的过程中可能会遇到的一些问题以及解决方法。

工欲善其事,必先利其器

要写代码,首先至少得有一个编辑器。 Perl 是跨平台的一种解释型语言,可以在 Unix/Linux/Windows/Mac 等平台上运行。具体对应平台上的编辑器,最简单的方案是 Unix 下用 vi Windows 下用 UltraEdit 。当然也有商业化的 IDE ,不过我尝试了一下发现并不是那么的好用,因此我在 Windows 平台上以 UltraEdit 作为编辑环境,完成后移植到 Solaris 平台上。

关于环境的搭建,有这样几个需要注意的地方:

1、 Windows 平台下对应的是 ActivePerl ,可以免费下载。

2、 UE 的网站上下载 Perl AutoComp 文件,可以实现自动完成功能。

3、 下载 Perl 对应的语法加亮的 Tag 文件并加入到 UE 中,可以更块的发现拼写错误。

4、 UE 设置一个快捷工具,命令行为 C:\Perl\bin\perl.exe "%F" (捕获输出),可以实现快速运行并显示结果。

5、 如果你不喜欢 UE ,那么我推荐 Source Insight

巧妇难为无米之炊

起始从某种角度来说,程序员和厨子是一样的。要做出一桌大餐来,首先得看看手上有什么原料,然后才能琢磨一下用这些东西能做出什么好吃的来。或者说想做什么东西,得先备好料才行。

看看我们现在都有什么:一个编辑器,一个 Perl 的开发环境,还有一个聪明的脑袋。这个任务中,我要处理命令行参数、访问 MySQL 数据库 (SQL) 、读写 XML 的配置文件以及输出一个固定格式的报表文件。

好了,去查查资料,看看访问数据库和读写 XML 都需要什么东西。正如同 C 语言本身带了很多标准函数库一样, Perl 本身也有函数库,并把这些函数库称为 Module (模块)。查了一下资料,发现要访问 MySQL 数据库需要 DBI DBD::MySQL 两个模块,那么去哪里找这些模块呢。这里给大家介绍一个 Perl Module 集散地 www.cpan.org ,这里包含了八千多个 Module ,可以从这里下载到几乎各种各样的 Module 。可以手工下载后安装,也可以使用工具来自动安装。在 Windows 下是可以使用 ppm 进行自动安装,例如 DBD 的安装过程如下:

C:\>ppm

ppm> search DBI

Searching in Active Repositories

一大堆与 DBI 相关的包的列表,其中就包括 DBI 这个包

ppm>install DBI

ppm>install DBD::mysql 如果知道模块的名字也可以直接安装

ppm>quit

如此就安装完成了。附带说一下, Linux 下没有 ppm ,但是有类似的方式。输入命令行

perl –MCPAN –e shell

然后 install DBI; install DBD-mysql ,和上面的操作几乎是一样的。

提示:如果是在 linux 下安装 DBD::Mysql 模块,需要把 mysql bin 目录包含在环境变量 PATH 中,否则会提示找不到 mysql_config 文件。 mysql 一般是安装在 /usr/local/mysql 下,因此可以通过执行命令行 PATH=$PATH:/usr/local/bin/mysql/bin 来将此路径加入到环境变量中。

访问 XML 有几种包可以选择:使用 DOM Simple 模块。 Simple 模块是把 XML Perl 的数组方式表示,而 DOM W3C 维护的一个基于树的 XML 文档标准。具体用哪种就看个人的需要了。我使用的是 DOM ,因此要安装 XML-DOM 包,方法同上。

说起编程语言,简单的来说无非就是这样几个必不可少的基本元素:变量、数据、表达式、流程控制语句(包括条件、分支、循环 ) 、函数、对象。具体到语言上,大部分的内容只是表达的形式不同而已。而 Perl C 又有什么区别呢?

首先要知道, Perl 是一种脚本语言。所谓的脚本,就是没有主函数,从最开始一行一行的按照顺序解释执行(老版 Basic 不也是如此吗)。因此,尽管把你的思路转化为流程用 Perl 表达出来吧。

其次, Perl 的设计中参考了很多语言的长处,并避免了设计上的缺陷。因此 Perl 的很多语法你可能都会觉得似曾相识。我把 Perl 的语法总结了一下,和 C 语言做了一个简单的对比表格。表格左右两边的语句是 C Perl 对应表达同一个功能各自的不同方式。如果读者有C语言的经验,相信看到这个对比可以很快的上手吧?

if 结构可以反转,意义不变,注意前句没有分号。

顾名思义 , unless 是“除非”的意思。这里的四个表达方式是等价的。注意第一种方式中,条件部分的圆括号和语句部分的花括号是不可省略的。

foreach (@arry)

foreach my $key(@ary)

foreach $count (1..10)

for/while 的语法都和 C 类似。

foreach 关键字也可以用 for ,意义不变。

int max(int x, int y)

return x>y?x:y;

int n=max(1,2);

sub max

my ($x, $y)=@_;

return $x>$y?$x:$y;

my $n=max(1,2)

注意下划线 ”_” 也是一个合法的变量名。而 @_ Perl 内置的一个数组,内容为函数的参数。

my ($x, $y) 表示声明了一个有两个元素的数组,并将两个元素映射到 $x $y 上。

($x,$y)=@_; 则表示两个数组之间的复制, @_ 中对应的元素的值就赋值给了 $x $y. 这是一个简便的写法,也可以这样写

my $x=$_[0]; my $y=$_[1];

return 是可选的,默认返回最后一个表达式的值

1. 编译时打开编译器所有的警告选项

2. 使用 lint 工具

3. perl –w myprogram.pl 打开运行警告开关,如果运行时 Perl 检查到了可能的错误,会显示警告信息,否则它默认是什么也不提示继续执行。

4. #!/usr/bin/perl –w 在代码文件第一行中加入 -w 选项开关

5. use strict; 使用严格语法约束

编译后直接执行

1. perl myprogram.pl 手工执行

2. #!/usr/bin/perl

Unix 下在代码第一行加入,然后给文件加上可执行的属性 chmod +x myprogram.pl ,之后就可以用 ./myprogram.pl 命令来运行。

3. Windows 下,安装 ActivePerl 的时候,已经将 .pl 后缀的文件和 perl 的解释程序关联起来了,因此直接双击文件图标就可以运行。

需要说明的是,在 Perl 的世界中有一句名言“条条大路通罗马”, 这句话的意思是说同样一件事情 Perl 允许你用很多种不同的方式去做。因此上表的例子风格是按照 C 的习惯来写的,并且为了简化起见,只是挑选了与 C 相似的内容。事实上, Perl 包含了很多 C 没有的东西,例如内置的 Hash 表、队列、正则表达式、格式定义等等。

从框架开始

Perl 有很多表达方式,我们可以选择一种自己熟悉、容易理解的方式来写 Perl 的程序。例如,你是一个经验丰富的 C 程序员,那么你可以选择以 C 的风格来写 Perl 程序。下面是一个小小的样板框架

#!/usr/bin/perl -w

use strict;

# 程序开始的第一行语句,调用 main 函数

main();

# 定义 main 函数

sub main

在这个框架下面,你几乎可以容易就开始你的 Perl 开发了。如果需要处理命令行参数,就可以稍微的扩展一下这个框架。

#!/usr/bin/perl -w

use strict;

use Getopt::Std;

main();

my $configfile;

sub ProcessOptions

my $VERSION = ' 1.0.0 ';

my $USAGE = "pp.pl [-v | -c configfile]\n";

my $opts={};

die $USAGE unless( getopts("c:v", $opts) );

die $VERSION if ($opts->{'v'});

$configfile=$opts->{'c'} ? $opts->{'c'} : 'config.xml' ;

sub main

ProcessOptions();

print $configfile;

实际上,剩余的工作和以往的工作差不多了,编写一个一个的函数,并实现你的业务逻辑。对于你这样一个聪明的程序员来说,学会 Perl 是一个很容易的事情。

以我的学习经验来看,在开发的过程中可能有一些常用但是很分散的细节问题会让你感到困惑。

1、 程序的入口参数怎么取?

内置数组 @ARGV 包含了所有的运行参数。可以打印出来看看 print @ARGV;

2、 函数如何传参数、取参数?

每个函数内部都有一个内置的数组 @_ ,这个数组的元素就是函数的参数。例如传入的第一个参数就是 $_[0] ,第二个是 $_[1] 。唔,如你所见, Perl 的函数参数就是 C 中的动态参数。

3、 默认变量是什么

这个可能会把你的头搞晕。有一个内置变量 $_

4、 显示消息、退出常见的简单写法

die ‘Error on program’;

也可以在条件不满足的情况下使用

die ‘Configuration error’ unless($doc->getDocumentElement);

5、 格式化输出

可以用简单的 print 语句进行一般的输出操作,如果需要复杂的格式化输出,可以使用 printf 语句……跟 C 的用法几乎是一样的。

printf("pi=% .6f ", 355/113);

6、 => 是什么东西 ?

在使用 Hash 表的时候,可以经常看到 => 这个符号。例如这样的一个定义 :

my $account={

'Simon'=> 'simon@email.com',

' Jesse '=> 'jesse@email.com'

其实, => 符号跟逗号 ”,” 是等价的。 Perl 里面的 Hash 表事实上是一个数组,只是把奇数位元素看做是 Key (键),而把偶数位的元素看做是 Value (值)。

7、 关于引用的一点说明

Perl 的引用类似 C 的指针,所谓的引用事实上就是地址。取一个变量的地址用反斜杠 ”\” 操作符,例如 $p=\$x; 那么 $p 就是一个指向 $x 变量的指针。要引用指针的值,使用 ”$” 操作符,例如 print $$p; 就是打印 $x 的值。

引用不单单可以引用变量,也可以引用数组、 HASH 表、函数,取函数的地址可以使用 * 操作符。

还能做什么

Perl 作为一个功能强大的脚本语言,可以应用在 Web 编程、数据库、 XML 、系统管理、图形图像、自然语言、压缩、加密、邮件系统、软件测试等各个地方。在 CPAN 上,你可以找到各种各样你所需要的模块支持。例如,你可以:

l 编写系统管理的脚本

l Apache 结合起来,编写 CGI 程序

l 编写动态网页

l 使用 Net 命名空间下的类编写网络应用程序

l 使用 Authen::Captcha 模块实现提交时的验证码的功能

l 使用 Storable 模块处理 Perl 的各种数据结构

l 使用 GD/Image::MagicK 模块处理图形

l 等等

www.perl.org Perl 的官方站点

www.perl.com O’Reily 维护的关于 Perl 的站点

www.cpan.org Perl Module 资源大全

www.perlchina.com 中国 Perl 协会

www.pm.org 世界各地的 Perl 用户组织

www.perlmonks.org Perl 写诗 J

http://www-128.ibm.com/developerworks/cn/linux/sdk/perl/ IBM 社区的 Perl 系列文章