例:简单的perl程序
#!/usr/bin/perl
print“Hello,word!\n”;
#!后表示pel的存放路径
在Perl 中,注释由#开始,直到本行结束,Perl 中没有“块注释”
perl语言中的一些特殊字符的意义
1。“->"是插入式解引用操作符,它是调用由引用传递参数的子程序的方法
2。”=>"是逗号的代替号
3。“::"相当于c语言的点,好比C++的类函数
4。"$"开头是标量
5。”@"开头的是数组
6。“%”开头的是hash函数或称为关联数组
7。“&"开头的是函数
undef
undef就是定义了一个变量却未赋值时候,这个变量的默认为undef值
将一个undef 的变量赋给另一个变量不会有什么问题,但如果print 某个未定义的值则将引起警告。
表数字和字符串的比较运算符
比较关系 | 数字 |
相等 eq | = = |
不等 ne | != |
小于 Lt | < |
大于 gt | > |
小于或等于 le | <= |
大于或等于 ge | >= |
<STDIN>用户输入
<STDIN>中的字符串通常由一个换行符作为结尾
$line =<STDIN>;
if($lineeq “\n”){
print“That was just a blank line!\n”;
}else{
print“That line of input was: $line”;
}
chomp函数,去除换行符
$text =“a line of text\n”; #也可以由<STDIN>输入
chomp($text);#去掉换行符(\n)。
chomp($text = <STDIN>); #读入,但不含换行符
$text =<STDIN>;
chomp($text); #同上,但用两步完成
defined
要分辨其是undef还是空串,可以使用defined函数,它将在为undef时返回false,其余返回true。
$madonna= <STDIN>;
If (defined($madonna)){
print“The input was $madonna”;
}else{
print“No input available!\n”;
}
$madonna= undef ; #同$madonna从未被初始化一样。
if
if($namegt ‘fred’){
print“‘$name’comes after ‘fred’in sorted order.\n”;
}else{
print“‘$name’does not come after ‘fred’.\n”;
print“Maybe it’s the same string, in fact.\n”;
}
花括号是必须的
Boolean类型
$is_bigger= $name gt‘fred’;
if($is_bigger){…}
Perl 是怎么判断其值得true 或false 呢?
●如果值为数字,0 是false;其余为真
●如果值为字符串,则空串(‘’)为false;其余为真
●如果值的类型既不是数字又不是字符串,则将其转换为数字或字符串后再利用上述规则● undef为false。所有的引用都是true。
这些规则中有一个特殊的地方。由于字符串‘0’和数字0 有相同的标量值,Perl 将它们相同看待。也就是说字符串‘0’是唯一一个非空但值为0 的串。
如果想得到相反的值,可以使用一元非运算符! 。如果其后面的是true,则得到false;反之,则得到true:
if(!$if_bigger){
#当$if_bigger非真时,运行此代码
}
my
my($num) = @_; #列表context,同($sum) = @_;
my $num= @_; #标量context,同$num = @_;
在第一个例子中,$num 得到第一个参数,因为其在列表context 中;
第二个例子中,将得到参数的个数,因为是在标量context中。
如果没有使用括号,my 仅定义一个变量
my$fred, $barney; #错误!没有定义$barney
my($fred, $barney); #两个均定义了
字符串-单引号
‘fred’#四个字符:f,r,e,d
‘barney’#六个字符
‘’ #空字符(没有字符)
‘Don’tlet an apostrophe end this string prematruely!’
‘thelast character of this string is a backslash: \\’
‘hello\n’#hello紧跟着反斜线和n
‘hello
there’#hello,换行,there (共11个字符)
‘\’\\’#单引号(’)跟着反斜线(\)
单引号字符串中的\n 不会被当作换行符来处理,其仅仅是两个字符\和n。只有在反斜线(\)后面接的是\或单引号’,其才会被当作特殊符号来处理。
字符串-双引号
“barney”#等同于‘barney’
“helloworld\n”#hello world,换行
“the last characterof this string is a quote mark:\””
“coke\tsprite”#coke, a tab(一个制表符), sprite
\n 换行
\r 回车
\t 制表符
\f formfeed
\b 退格
\a 响铃
\e escape(ASCII 中的escape 字符)
\007 任何八进制值(这里是,007=bell(响铃))
\x7f 任何十六进制值(这里是,007=bell)
\cC 一个控制符(这里是,ctrl +c)
\\ 反斜线
\” 双引号
\l 下个字符小写
\L 接着的字符均小写直到\E
\u 下个字符大写
\U 接着的字符均大写直到\E
\Q 在non-word 字符前加上\,直到\E
\E 结束\L,\E 和\Q
双引号字符串另一个性质是可进行变量内插,这是说当使用字符串时,如果字符串中含有变量名,将由变量的当前值替换它。
unless
在if 控制结构中,只有条件为真时,才执行块中的代码。如果你想在条件为假时执行,可以使用unless,unless 的含义是:除非条件为真,否则执行块中的代码。
unless($fred=~ /^[A-Z_]\w*$/i){
print“The value of \$fred doesn’t look like a Perl identifier name.\n”;
}
对比
if(!($fred =~ /^[A-Z_]\w*$/i)){
print“The value of \$fred doesn’t look like a Perl identifier name.\n”;
}
unless($mon =~ /^Feb/){
print“This month has at least thirty days.\n”;
}else{
print“Do you see what’s going on here?\n”;
}
对比
if($mon=~ /^Feb/){
print“Do you see what’s going on here?\n”;
}else{
print“This month has at least thirty days.\n”;
}
标量变量
标量变量可以存放一个标量值。标量变量的名字由一个美圆符号($)后接Perl 标识符:由字母,数字和下划线组成,但不能由数字开头。大小写是严格区分的:变量$Fred 和变量$fred
是不同的。
$fred =17; #将17赋给变量$fred
$barney=‘hello’; #将五个字母的字符串‘hello’赋给$barney
$barney= $fred + 3;#将$fred的值加上三赋给$barney (20)
$barney=$barney*2;#将变量$barney乘2再赋给$barney (40)
注意最后一行中$barney 变量使用了2 次:一次从中取值(等号右边)一次作为赋值的对象(等号左边)。
另一个常用的赋值操作符是字符串连接符号(.);其赋值形式为(.=):
$str =str . “”; #$str后接空格
$str .=“”’; #同上
print“hello world\n”; #输出helloworld,后接换行符
print“The answer is ”;
print 6* 7;
print“.\n”
也可以将一串值赋给print,利用逗号分开:
print“The answer is ”,6*7, “.\n”
变量值内插
$mean =“brontosaurus steak”;
$barney= “fred ate a $meal”; #$barney现在是“fred ate a brontosaurus steak”
$barney= ‘fred ate a’. $meal; #同上
如果一个变量未被赋值,则将使用空值替换:
$barney= “fred ate a $meat”; #$barney现在是“fred ate a ”
如果使用的是单独一个变量,是否使用引号没有影响。如:
print“$fred”; #引号是没有必要的
print$fred; #更好的写法
在字符串中变量前($符号前)加上反斜线(\),变量将不会被内插(替换):
$fred =‘hello’;
print“The name is \$fred .\n”; #打印出美圆符号,变量不会被其值替换
Perl 提供了一种类似于shell 的分隔符:花括号({})。用花括号将变量名括起来。或者将字符串分隔成几个部分,再用连接符(.)串起来:
$what=“brontosaurus steak”
$n = 3;
print“fred ate $n $whats.\n”; #不是steaks,而是$whats的值
print“fred ate $n ${what}s.\n”; #现在是使用变量$what
print“fred ate $n $what”. “s.\n”; #另一种方法
print‘fred ate ’. $n . ‘’. $what . “s.\n”; #一种复杂的方法
数组
$fred[0]= “yabba”;
$fred[1]=“dabba”;
$fred[2]= “doo”;
数组名字(本例中:fred)和标量是属于完全不同的命名空间(namespace)。同一程序也可以同时包含叫做$fred 的标量变量。Perl 将它们当作完全不同的事物来看待,不会混淆
下标可以是任何能返回数值的表达式。如果其值不为整数,则自动将其转换为小于它的最大整数值:
$number= 2.71828;
print$fred[$number-1]; #和print$fred[1]一样
如果下标超出了数组的范围,则其值为undef。这和通常的变量情况是一样的,如果没有值存放在变量中,则其为undef。
$blank= $fred [142_857] #此数组元素未存放值,得到undef
$blanc= $mel; #$mel未存放值(未初始化),得到undef
$rocks[0]= ‘bedrock’; #一个元素
$rocks[1]= ‘slate’; #又一个
$rocks[2]= ‘lava’; #又一个
$rocks[3]= ‘crushed rock’;#又一个
$rocks[99]= ‘schist’; #现在有95个undef元素
经常将$#name 的值作为索引
$end =$#rocks; #99,最后一个元素的索引
$number_of_rocks= $end + 1; #正确,但有更好的方法
$rocks[$#rocks]= ‘hard rock’; #the last rock
数组的负数索引值从最后一个元素开始
$rocks[-1]= ‘hard rock’; #完成上例中的一种更简单的方法
$dead_rock= ‘rocks[-100]’; #得到‘bedrock’,第0个元素
$rocks[-200]= ‘crystal’; #严重错误(fatalerror!)
数组列表
数组是由括号括起来并且其元素由逗号分隔开的列表。这些值组成了数组的元素:
(1,2,3)#含有1,2,3的列表
(1,2,3,)#同上,最后一个逗号被忽略
() #空列表-0个元素
(1..100)#包含100个整数的列表
最后一个例子使用了范围操作符(range operator)..,它创建了从左值到右值之间所有值的列表。
(1..5)#同(1,2,3,4,5)
(1.7..5.7)#同上— 最小值和最大值被转换成整数
(5..1)#空列表— ..中的左值应小于右值,否则为空
(0,2..6,10,12)#同(0,2,3,4,5,6,10,12)
($m..$n)#由$m和$n的值决定
(0..$#rocks)#上节中有$#rocks的介绍
从上面最后两个例子中可以看到,列表中的元素并非必须是常数,也可以是在执行此语句时再计算值的表达式:
($m,17)#两个值;$m的当前值,和17
($m+$o,$p+$q)#两个值
当然,列表可以包含任意的标量值,如下面的包含字符串的例子:
(“fred”,“barney”, “betty”, “wilma”, “dino”)
字符串的列表
qw(fredbarney betty wilma dino ) #同上,但输入更少
由于qw 是一种引用,因此不可以在qw 内添加注释。
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[fred barney betty wilma dino ]
qw<fred barney betty wilma dino >
如后面四个例子中显示的那样,有时两个分界符是可以不同的。如果开分界符有一个对应的闭分界符,那对应的“右”分界符则为其闭分界符。
列表赋值
($fred,$barney, $dino) = (“flintstone”, “rubble”, undef);
($fred,$barney) = ($barney, $fred) #交换两个变量
($betty[0],$betty[1])= ($betty[1],$betty[0]);
如果变量个数(等号左边)不同于其值的个数(等号右边),将发生什么事情呢?在列表赋值中,额外的值会被自动忽略。
($fred,$barney) = qw <flintstone rubble slate granite>; #两个值被忽略了
($wilma,$dino)= qw[flintstone]; #$dino为undef
引用数组
当想引用这个数组时,Perl 有一种简单的写法。在数组名前加@(后没有中括号)来引用整个数组。
@rocks= qw / bedrock slate lava /;
@tiny =(); #空表
@giant= 1..1e5; #包含100,000个元素的表
@stuff= (@giant, undef, @giant); #包含200,001个元素的表
@dino =“granite”;
@quarry= (@rocks, “crushed rock”, @tiny, $dino);
最后一个赋值语句将五个元素(bedrock, slate,lava, crushed, rock, granite)赋给变量@quarry,因为@tiny 没有元素。(特别的是,它没有undef 这个值,但可以像@stuff 那样明确的指定它。)还有一点需要注意的是数组名字被其列表值替换。数组不能成为列表的一个元素的原因是数组只能包含标量值,不能包含其它的数组。没有赋值的数组变量的值为( ),空表。和
未初始化的标量变量为undef 类似,未被初始化的数组为空表。
当将一个数组拷贝到另一个数组时,仍然是列表赋值。如下例:
@copy =@quarry; #将一个数组中的值拷贝的另一个数组中
context
42 +something #something必须是标量
sortsomething #something必须是列表
如果something 是相同的字符串,在一种情况下,它返回一个变量值,在另一种情况下,它可能返回列表。Perl 中的表达式将根据其context 返回适当的值。例如,一个数组的“name”,在列表context 中,它返回列表元素;在标量context 中,它返回数组元素的个数:
数组@people 的真实名字是people。@只是一个限定词(qualifier)。
@people= qw( fred barney betty );
@sorted= sort @people; #列表context:barney , betty, fred
$number= 42 + @people; #标量context:42+3,得到45
甚至普通的赋值(赋给标量或者列表)也产生不同的contexts:
@list =@people; #3个People的列表
$n =@people ; #数字3
die
当Perl 内部发生了一个严重错误(fatalerror)(例如,除数为0,或者使用了无效的正则表达式,或者调用了一个未声明的函数),程序将停止运行,并告诉你失败的原因。可以利用die 函数来创建我们自己的严重错误。
die 函数将打印出你给它的消息(利用标准错误流),并确保程序退出时为非零(nonzero)的退出状态(exit status)。
if(!openLOG, “>>logfile”){
die“Cannot create logfile:$!”;
}
如果open 失败,则die 将结束程序,并告诉你不能创建logfile。但,消息中的$!是指什么呢?它是系统产生的一些可读的信息。
die 还会为你做一件事:他会自动将Perl 程序的名字和行数输出在消息的末尾,因此能轻易的辨别出是哪一个die 引起的错误。
上述代码如果含有权限不够(permission denied)的错误,则其消息如下:
Cannot createlogfile: permission denied at your_program line 1234.
sprintf
sprintf函数的参数和printf 的参数完全相同(除了可选的文件句柄外),但它返回的是被请求的字符串,而非打印出来。
my$data_tag = sprintf“%4d/%02d/%02d %02d:%02d:%02d”,$yr, $mo, $da, $h, $m, $s;
在上例中,$date_tag 得到像“2038/01/19 3:00:08”这样的值
格式字符串(sprintf 的第一个参数)在某些格式化数字前使用了前置0,格式化数字中的前置0 的含义是,如果需要,在前面加上0,使之达到需要的宽度。格式中如果没有前置0,则日期-时间的结果字符串中,我们得到不需要的空格,而非0,看起来像“2038/1/19 3:0: 8”
一种常用sprintf 的地方是,你需要给定数字的小数点后面几位,例如需要将某个金钱数量显示为2.50 而非2.5 也不是2.49997!这使用“%.2f”很容易做到:
my$money = sprintf “%.2f”, 2.49997;
子程序中的私有变量
Perl 在每一次调用时提供@_这个私有变量,默认情况下,Perl 中所有变量都是全局的;也就是说,这些变量可以在程序的任意部分使用。你也可以任意时候使用my创建私有变量:
sub max{
my($m,$n);#新的,私有变量
($m,$n)= @_; #赋值
if($m> $n) {$m} else{$n}
}
这些变量是此代码块中的私有的(或者局部的)变量;别的$m 和$n 不会影响此处的两个变量。而且,其它地方的代码不能访问或者修改这些变量。你可以将此子程序放在任意地方而不用担心它们会和程序其它地方的$m,$n(如果有)变量混淆。在if 代码块内部,其语句没有分号。Perl 允许省略括号中最后一条语句的分号,在实际代码中,通常仅当此代码
块仅包含一条语句时才省略此分号。
my($m,$n)= @_;
上面的一条语句创建了一些私有变量并给它们赋值,第一个为$m,第二个为$n。
几乎每一个子程序都由类似的语句开头。当看见那一行时,你就知道此子程序需要2 个变量,在此子程序中非别被叫做$m 和$n。
哈希
要访问hash 元素,可以使用下面的语法:
$hash{$some_key}
这和访问数组元素的方法有些类似,这里下标(key)上使用的是花括号({}),而不是方括号([ ])。现在key 的表达式是字符串,而非数字:
$family_name{“fred”}= “flintstone”;
$family_name{“barney”}= “rubble”
对比数组
$family_name[0]= “flintstone”;
$family_name[0]= “rubble”;
对比数组列表
@ family_name=(“flintstone”,“rubble”);
@ family_name=qw<flintstonerubble>;
当将某个值存储在已经存在的hash 元素中,以前的值会被覆盖:
$family_name{“fred”}= “astaire”; #将新值赋给已经存在的元素
$bedrock= $family_name{“fred”}; #得到“astaire”;以前的值丢失了
访问不存在的hash 元素得到undef:
$grantie= $family_name{“larry”}; #没有larry:得到undef
要引用整个hash,使用百分号(“%”)作为前缀。前面中使用的hash 的名字为%family_name。
为了方便,hash 可以转换为列表,或者反过来。给hash 赋值,其类型属于列表context 赋值,其中列表是key/value 对
%some_hash= (“foo”, 35, “bar”, 12.4, 2.5, “hello”, “wilma”, 1.72e30, “betty”, “bye\n”);
hash 的值(在列表context 中)是一个key/value 对的列表:
@array_array= %some_hash;
我们把这称为:将hash 展开,并将其key/value 对返回到一个列表中。返回的key/value 顺序和存放的顺序可能不同:
print“@any_array\n”;
#可能得到如下的结果:betty bye(换行),wilma 1.72e+30 foo 35 2.5 hello bar 12.4
虽然key/value 对的顺序是杂乱的,但返回的列表中每一个key 和其value 是连在一起的。因此,虽然我们不知道key:foo会出现在什么地方,但我们知道其value:35 会紧随其后。
在hash之间拷贝:
%new_hash= %old_hash;
这段代码告诉Perl 将%old_hash 展开成key/value 的列表,再将其赋给%new_hash,其将key/value 对一个一个加入的。
将hash反转:
%inverse_hash= reverse %any_hash;
这会将%any_hash 展开成key/value 对的列表,其列表如(key,value,key,value,key,value,……)。然后, 将其反转,得到(value,key,value,key,value,key,……)。value 和key 的位置交换了。当将其存放在%inverse_hash,你可能猜测(按照科学的方法,如果你足够聪明)这仅当值也是唯一的情况才能正常工作。否则,我们将得到重复的key,但key 必须是唯一的。这里有一条规则:最后一次赋值获胜。也就是说,列表中后面的元素将覆盖掉以前的元素(相同key
时)。由于我们并不知道key/value 对的顺序,因此也不能判断哪一对将最终获胜(被使用)。如果想使用这种技术,那你必须确保之前的值是唯一的
=>
当给hash 赋值时,有时并不明显哪些元素是keys,那些是values
Perl 语法中,在需要逗号(,)的时候,都可以使用大箭头符号替换;对于Perl 来讲,它们是一样的
my %last_name = (
“fred” =>“flintstone”,
“dino” => undef,
“barney”=>“rubble”;
“betty”=> “rubble”,
);
上面代码中,很容易辨别出哪一个是key,哪一个是value。注意列表中最后一个逗号。这个逗号是没什么用的,但有时能给我们带来方便;如果我们要加入新的元素到hash 中,我们只需知道每一行都有key/value 对,结尾有逗号。Perl 会查看不同元素之间的逗号,以及列表结尾处的逗号(此逗号非必需的)。
keys 函数会返回此hash 的所有keys,values 函数将返回所有的values。如果hash 中没有元素,则此函数将返回空列表:
my%hash = (“a”=>1, “b”=>2, “c”=>3);
my @k =keys %hash;
my@v =values %hash;
现在,@k含有“a”, “b”, “c”,而@v含有1, 2, 3,其顺序可能不同
my$count = keys %hash; #得到3,是指有3个key/value对
有时,你可能看到有人将hash 作为boolean(true/false)表达式来使用:
if(%hash){
print“That was a true value!\n”;
}
上述语句为true,当且仅当其至少含有一个key/value 对
数据库和DBI
DBI(数据库接口(database interface))模块不是Perl 默认附带的,但它是最常用的模块之一,因为大多数用户都需要连接到某种类型的数据库上
当安装了DBI 后,也需要安装DBD(数据库驱动程序(database driver))从CPAN 上搜索DBD,会返回一长串的结果。根据数据库服务器,及其版本安装正确的数据库驱动程序。
useDBI;
$dbh =DBI->connect($data_source, $username, $password);
$data_source 含有需要使用的DBD 的信息。对于PostgreSQL,驱动是DBD::Pq,则$data_source看起来如下:
my$data_source = “dbi:Pg:dbname=name_of_database”;
一旦连接上数据库后,则进入了preparing,executing, reading 查询的循环。
$sth =$dbh->prepare(“SELECT * FROM fooWHERE bla”);
$sth->execute();
@row_ary= $sth->fetchrow_array;
$sth->finish;
当结束时,需要断开和数据库的连接。
$dbh->disconnect();