CGI/PERL学习如果你曾经使用过linux,无论时间长短,都必定听说过perl;甚至可能在不知道的情况下运行了不少perl的脚本。很多服务程序,象“inews”、“mirror”、“debconf”、“majordomo”、“sirc”等等,都是纯粹用perl写的。在Debian区域的“Packages.gz”文件里做一个简单的的“zgrep”,你就可以知道有382个包需要perl的支持(也就是意味着这些包都至少有一部分是用perl写的。),其它28个软件包也建议或推荐使用perl支持。
但是Perl语言有什么出色之处呢?
CGI/PERL学习"Perl语言在文本处理方面非常突出,它把不同的内容联成一个整体。对于这种脚本语言来说所有的那些不同的元素,看起来都是一样的。”——John Ousterhout,Tcl脚本语言的作者
Perl即“Practical Extraction and Report Language”(实用析取报表语言)。是的,比较粗,但是我想那就是你所得到的——如果你打算确信$HUNN NGOUS CORP并且使用它的话。事实上,Larry Uall< Larry@wall org >(Perl的创立者)在Perl的帮助手册页里提出:“Perl实际上代表的是Pathologically Edectic Rubbish Lister,但不要告诉任何人我这样说过。”唔,他是Larry,对此我又能再说些什么呢?
Perl已经被广泛的认为是“一种拥有各种语言功能的梦幻脚本语言”、“Unix 中的王牌工具”。以及其他的一些类似的称呼,这些都是赞誉之辞,Perl被用来写单行脚本,快速执行程序,大的规划项目(Amazon.com的所有评论产品和控制系统,Netscape的内容策划管理和传送系统,人类整组基因工程的DNA排序以及计划管理等等)。还有数以百万计的令我们惊讶的各种各样的事情的高速程序。Perl还能够实现许多UNIX的公共系统工具的功能(提示:如果你正在学或必须学awk, sed, grep和 tr,我建议你以Perl来代替它们。所有的功能,更快的执行效率,相信你将永远不会因为它的性能发展太快而不适应它。)
就像你对所有的现代语言所期望的那样,Perl允许你建立面向对象的程序。它也可以进行网络操作(例如socket等等),并且有良好的可移植性(一个写得好的脚本可以在Linux,BSD,Solaries,Dos,Win9x,NT,MacOS,OS/2, AnugaOS,VMS等操作系统中不需要任何修改的运行),编写和调试周期很短——由于没有编译的要求,你只需将变化的部分写出,就可以运行脚本。还有数目庞大的可适用于执行任何一项任务的模块(即预建立Perl的例程),Comprehensive Perl Archiue Network (CPAN)就是每一个Perl程序员所能拥有的最好的模块库之一。
CGI/PERL学习哦,但那是真的吗?
问得好,我希望在你使用Perl大约一年之后,就能告诉我答案。一样东西的描述就像一个容器……,我仍旧在试图寻找一个适合Perl的足够大的容器(要是带有能锁的盖子就更好了)。
那Perl不适用的方面呢?
我不会用Perl去写一个GUI文字处理程序,一个图形游戏,或者一个图形浏览器。Perl能通过与许多其他语言的接口真正的交互,所以你可以实现刚才所说的全部程序。但在我看来,在其它编程语言里有许多更有效的方法去做那些事情。“对一个拿着锤子的人来说,所有的问题看上去都像是钉子”——程序员们小心了。
值得注意的是,Perl本身并不是用Perl写成的,也不是Linalx的内核。那些底层的事务用C/C++来处理会更好的。“用最适合的工具去做最适合的工作”应成为每个程序员的座佑铭。
在拉开跳伞索之前的最后一次告诫。
如果你对Perl有一点了解,或者看过《Aint The Way I Learned It》系列内容的话,一定记得Perl的口号:“做事总有不止一种办法(There's More Than One Way To Do It)”。这常被缩写为TMTOMDI,并称为“tim-today”,是Perl的核心观点之一。当然,任何对明显的错误的订正都非常欢迎。
那些看过我早些时间写的关于Shell脚本的丛书的人也许记得,一个脚本开始都有被称作hash-bang或shebang的行:
#!/bin/ bash
这行告诉外壳(shell)派生一个subshell(子shell),随后的代码将被这个特定的subshell程序解释执行。Perl脚本也一样,第一行必须是:
#!/usr/bin/Perl
或者任何一个正确的Perl解释器的路径。
注意到Hash-bang的必要条件:
1) 它必须是在脚本中的第一行。
2) #号必须是本行的第一个字母,并且在#号和!号之间不能有任何字母或符号。
3) 必须使用绝对的路径,而不是只有可执行程序的名称。
下面,让我们试着写出我们的第一个 Perl脚本:
#!/ usr/bin/Perl
# "goodbye" - a modern, high-angst replacement for "Hello World"
print "Goodbye, cruel world!
";
unlink $0;
嗯,至少在离开以前说了“再见”;礼貌夫人都会为此骄傲的。我们在这个脚本里做了什么呢?有几件事情是相当明显的:第一,“hash-bang”,第二,一行告诉我们脚本要做什么的说明—从shell脚本发展出来的另一个东东,并且这是个不错的想法(在代码中并没有过多的解释!)。第三,我们用“print”函数打印出所要的信息。注意,在一串字符末尾的“ ”:Perl不会自动为你提供一个换行,所以你必须自己决定要还是不要。还要注意,在每一行代码末尾的分号:就像C语言,Perl也有同样的要求,不幸的是这常被编程者所忘记。实际上,由于有着相对易懂的信息,Perl的错误检查十分容易,作为代码语句的分隔标志,分号常被认为是下一行的前导符。如果你注意到这个问题,并不麻烦,最好记住使用分号。
CGI/PERL学习最后一行的意思是删除 “goodbye cruel world”文件,符号“$0”仅仅是被运行堵塞的脚本的名字的引用,“unlink”做了和“rm”一样的事。注意,“$0”比“goodbye”甚至是“/goodbye”有用的多,不管文件是什么名字,“$0”将返回这个文件名。
写完美无缺的代码对我来说有一些不切实际。在过去的一些场合,我写了些“write-only”代码,这将使任何试着读它的变成不同的颜色。我经常尝试着提高水平,我真的希望看到这个想法得以实现。
空白——tab和space键——在Perl中受到了忽略,也就是说,它是无所谓有无所谓无的。正因为这一点,你能格式化你的Perl代码来表达你正想要表达的思想,举个比较简单的例子;
@boats=(“Aloa”,“Cheoy Lee”,“Pearson”,“Mason”,Swem,“Westsail”,“S2”,“Petersen”, “Hereshoff”);#海船的名单列表。
这个例子中,我们用一些海船的名字填入数组“@boats ”中,下面的例子也许更加容易理解:
@array=(“Aloa”,#法国OSTAR/IOR的船
“Cheoy Lee”,#舒适但是昂贵
“Pearson”,#结实但是笨重
“Mason”,#设计良好,但有些雍肿
“Swan”,#上等船只,如果你是大款
“Westsail”,Westsail在双尾船里算是相当不错了
“S2”,#漂亮的海湾船只——但不适宜远洋
“Petersen”, #钢铁巡洋舰,宽敞但援慢
“Hereshott”,#快速而华丽,狭窄而昂贵
这个习惯不仅仅在Perl中得到应用。绝大多数的现代语言允许附加空白,这样可以使代码更加易懂。当我写这个系列文章的时候,我将尽最大努力示范至少我自己认为好的代码样式的版本。同时也希望每一个人在创建他们自己的代码时认真考虑这件事。
变量CGI/PERL学习
在Perl里,易用性非常重要的。它是一种被称作“格式宽松”的语言,其中变量的定义并没有严格要求。实际上,没有什么方法可以定义32位的浮点数变量。
Perl中有三种变量,它们分别是标量型变量(Scalars),数组型变量(arranys)和散列表(hashes),除了这些颇令人头疼的名字,他们其实都很简单:仅仅包含一些数据的不同排列而已。
标量型变量——数字,字符串和引用
一个标量型变量由$标志来表示,例如$nuru,$joe,$pointer。
例:
“0.0421”,“Joe’s gloue”,内存地址“0Xa000”
数组型变量——联系数字标识的标量型变量的列表或者说集合
一个数组型变量由@标志来表示,例如@v,@list,@variable
例:
0-----“Sundary”
1-----“Mondeny”
2-----“Tuesday”
3-----“Wednesday”
散列表——标量型列表的引用键
一个散列表变量由%标志来表示,例如%people,%x,%this_is_a_hash。
例:
ridcnt ——“Sherlock Holmes”
addr——“221B Backer Street”
code—“NW1”
city—“Londen”
country—“Steuth”
……
注意,虽然数组型变量是按数字顺序存储的,但散列表却不是——恢复散列表的第一个元素的往往和你载入的第一个元素毫无关联。散列的元素通过文本键代替它们在结构中的位置来进行索引。
利用这三种数据类型,你可以表示你想要的任何事,并且会很轻松的实现。
另外很重要的一点:$a,@a 和%a三者之间完全毫无关联,他们处在不同的名字空间。我在设计程序时,尽量小心不使用这些在视觉容易产生混淆的名字。特别是像$a[0](数组@a的第一个元素的引用)这种变量已经存在的情况下——这的确是你需要注意的。
可以给变量赋不同类型的值——数字型和字符串——我们下一步将进行有关两种类型的共同的操作。Perl为你提供这些,但应该记住哪些类型的用哪些操作符。
Operator Num Str
等于 == eql
不等于 != ne
小于 < Lt
大于 > gt
小于等于 <= le
大于等于 >= ge
当通过比较这些字母或字符串之后会觉得他们异常容易记忆和使用——比较字符的时候,就使用字符。
以前我总是给出具体的例子,但这次给你们出一道足以使你们头发变白,身心疲惫的难题:
#!/usr/bin/perl
# A Political evaluation script
$a=“A1”
$b=“George”;
if($a>$b)print $a wordinake a better Presideut
If($a<$b) print $b word make a betler Presiclent
;
If($a=$b)Print $a or $b, tlere’s no Diflereue
;
输出结果表明其中并没有什么不同,这也许只反映出一个政治性的现实,但我们比较出的结果又是什么呢?对了,我们应该使用字符串操作,不对吗?
#!/usr/bin/perl
# A political evaluation script
$a = "Al";
$b = "George";
if ( $a > $b) { print "$a would make a better President.
"; }
if ( $a < $b) { print "$b would make a better President.
"; }
if ( $a==$b) { print "$a or $b, there's no difference...
"; }
呵呵,输出表明它们俩没有什么不同的地方。这也许是政治上的真实反映,但对我们期望的比较输出却……哦,对了,我们应该使用字符串操作符,恩?
#!/usr/bin/perl
# A political evaluation script
$a = "Al";
$b = "George";
if ( $a gt $b) { print "$a would make a better President.
"; }
if ( $a lt $b) { print "$b would make a better President.
"; }
if ( $a eq $b) { print "$a or $b, there's no difference...
"; }
CGI/PERL学习现在,比较操作符才能正确的工作。(现实世界的逻辑却并非如此……我离题了。)
顺便提一下,在第一个例子中为什么Perl会认为“Al”和“George”是等值的呢?什么时候程序中参进了政治观点?
很重要的一点原因是,它要依赖Perl分辨“真(true)”与“假(false)”的方法。可以进行一些试验,如“if”,“while”,“wntil”等,根据实验的结果,我们可以理解这一点。
“0”意味着false,不管它是个数字还是字符串。
所有没有定义的变量(那些没有赋于任何值的量)都是false。
一个空的字符串——“”或‘’——也是false。
其余的都是true。
好了,这儿有一些较麻烦的例子,看看这些量,判断他们是true还是false:
“00” “-1” “ ” “5-5”
请在这篇文章的注1中寻找答案,这里先卖一个关子。
另外一个比较重要的问题是变量的输出,这是决定引号中的变量是否需要解释说明的方法,举例如下:
$name = ‘Bessie’;
print ‘Our cow is named $name。’;
输出为:
Our cow is named $name。
我并不认为如果那样叫的话,会有自我意识强烈的母牛到来(我已不打算再提发音的困难)。但是,我们怎样才能使Bessie显示出来呢?
#注意过去是单引号而现在是双引号的地方。
$name = ‘Bessie’;
print “Our cow is named $name。”;
通过Perl达到了我们的目的,我说过你可以做任何事情。
如果我们想打印变量的名字该怎么做呢?对Perl来说那太简单了:
$joe = “Joe”;
print “The variable $joe contains the value $joe。”;
我们可以打印出任何转义字符——也就是说字符在 Perl中有特殊的含义——但需在他们前面加一个反斜杠。看看下面的例子:
$joe = "Joe";
print "The variable "$joe" contains the value "$joe."";
唔…… TMTOWDI:
print 'The variable "$joe" contains the value "', $joe, '".';
按照你自己的选择,一定要理解他们之间的不同之处,注意在“print”语句中使用逗点作为分隔符的重要性,没有这个逗点,语义将截然不同,这一点我们将在以后的文章中讨论。
在结束这篇文章之前,还有一点应重点考虑,为创建脚本文件时,通常使用“-W”参数作为hash-bang的一部分:
#!/usr/bin/perl -w
这样会对脚本中的问题发出警告,并指出这些问题的所在,如果你是一个Perl的初学者一定要记住这个用法,但如果你是一个Perl的专家那就更会记住使用这个开关。那些错误不会随着你的进步而消失,他们会很兴奋的增多:)。
尾声
这段时间,我们进行了一段短途旅行,伴随着一段轻快的爵士乐,我们轻盈的跳过巨岩和戈滩,下个月我们将向更深的层次进展;也许研究数组或散列表,也许向拥有不可思议的强大功能的“常规表达”或Perl的regexes发起冲刺,此时,我建议尝试一些我们已经讨论过的东西,或许自己做一些实践,我发现了最好的学习语言的方法,勇往直前直到极限,然后把我所遇到的困难向比我了解的更多的人请教,如果你不知道问题的话你就不会得到理想的答案。
CGI/PERL学习各位Perl之旅愉快。
Ben Okopnik
perl -we '$@="145143150157404211216516316440141156 ".
"1571641501451624012014516215440110141143153145162".
"424076405714414516657164164171";`$@`'
注释[1];全是true,他们都不符合“假”的范围:“00”与“0”不同;“-1”也与“0”不同,空格“ ”,并不是空的字符串( ),“5-5”,没有核定,并不是“0”,参考书:“Perl:The Complete Reference”,Martin C. Brown
有关Perl的专有名词
Perl——纵览
Perltoc——TOC文档
PerlSYN ——语法
Perlrun——执行
Perltrap——容易犯错之处
Perlfaq——常见问题
Perldate——数据结构
Perlop——操作和优先权
Perlfunc——内建函数
Perlkstyle——格式向导
Perldoc 和 Perldoc-f