基本信息
Perl一般被称为“实用报表提取语言”(Practical Extraction and Report Language)。Perl 最初的设计者为拉里·沃尔(Larry Wall),他于1987年12月18日发表。Perl借取了C、sed、awk、shell scripting以及很多其他程序语言的特性。其中最重要的特性是它内部集成了正则表达式的功能,以及巨大的第三方代码库CPAN,即Perl综合典藏网(Comprehensive Perl Archive Network)。
Perl的特点
1.简单。解决一个一般的问题用它几行代码就完成了. 一个稍复杂一点的问题代码也不会超过一屏!
2.可移植性强。几乎可以在任何地方任何操作系统运行。
3.几乎不受限制。小程序大程序都适合用perl编写。数组和哈希等没有最大限制,你可以将内存填满。
4.速度很快。因为是开源的语言,所有的开发者同时也是用户。
5.难以阅读。Perl的灵活性和“过度”的冗余语法,也因此获得了write-only的“美誉”,因为许多Perl
程序的代码令人难以阅读,实现相同功能的程序代码长度可以相差十倍百倍。但Perl同样可以将代码
书写得像Python或Ruby等语言一样优雅。
Perl适合做的事情
1.合适在三分钟内写出“急功近利”的小程序,也可以编写用处广泛需要很多人完成的大型程序。
2.擅长处理文字。约有90%与文字处理有关。
Perl语法(perl是从上到下执行的)
1.标量。也称变量,以$开头,包含数字和字符串,两者可以相互转换。注:单引号中的字符串表示它本身;双引号中如果有反斜线或八进制十六进制写法,表示转换后字符。
变量定义:my $abc=123;
2.列表和数组。数组以@开头,如@fred=(1,2,3),数组中的元素用@fred[0],@fred[1]表示。perl支持数组内插,例如:
@rock=qw{stone slate rubble};
pint "quartz @rock limestone";#输出五种以空白隔开的石头。
3.Perl的“老地方”:$_。当语句中省略变量名称的时候,系统会自动使用它的“老地方”变量。例如读文件的每一行,默认都是$_;
4.子程序。通常以&开头,可省略但最好别省略。类似于方法。
sub marine {
$n+=1;
pint "Hello,sailor number $n!\n";
}
子程序通常情况下是全局的,可以放在程序的任意位置,且不需要事先声明。如果定义了两个相同名称的子程序,后面一个会覆盖前一个。可以在任意表达式中调用子程序 &marine。所有的子程序都有返回值,返回值即是最后一次的运算结果。
另外,子程序可以带参数,参数存在数组变量@_中,该变量在子程序执行期间有效,按顺序依次为$_[0],$_[1]。
默认情况下,所有的变量都是全局变量,子程序中(其他任何语句块如foreach、if同样)也可以变量私有,my($m,$n)。注:my在不加括号是,表示私有化单个变量 my $fred,也可以私有化数组 my @phone
Perl的著名特性:哈希
所谓哈希就是一种数据结构,和数组的相同之处在于:可以容纳很多值(没有上限),并能随即存取;而区别在于:不像数组是以数字来检索,哈希是以名字来检索。也就是说,检索用的键不是数字,而是保证唯一的字符串。哈希里没有顺序,只有一些键/值对。perl在键/值对增多时并不会变慢。
哈希的应用:
1.按名字找姓;
2.用主机名找IP地址;
3.按单词统计出现次数;
4.按驾驶执照号找出姓名。
哈希的使用:
1.给哈希赋值:%any_hash=("a"=>1,"b"=>23,"c"=>543)
2.访问哈希:$family_name{"fred"}
3.访问整个哈希:�mily_name
4.哈希松绑:@any_arry=%some_hash
5.建立反转哈希:%inverse_hash=reverse %any_hash
----------读文件赋值给hash-----------
sub readUid2Mobile()
{
my($uid,$mobile);
if(-e $uid2mobileFile)
{
open (FP, "$uid2mobileFile") || return -1;
while(<FP>)
{chomp;#去除行末尾换行
($uid,$mobile) =split(/\t/)#以\t分隔
$uidMobile{$uid} = $mobile;#往hash里赋值
}
close FP;
}}
Perl另一特色:对正则表达式强有力的支持
由于Perl的主要功能是处理文字,正则表达式在这里起到关键作用,本文暂不做介绍,以后单独一个篇幅介绍。
Perl的控制结构
1.if 判断
if ($name gt 'fred'){
print "'$name' comes after 'fred' in sorted order.\n";
}else{
print "'$name' does not comes after 'fred'.\n"
}
2.while:循环
$count = 0;
while ($count<10){
$count +=2;
print "count is now $count\n";
}
3.foreach:遍历数组中的值
foreach $rock (qw/bedrock slate lava/){
print "one rock is $rock.\n";
}
my @mobilelist = qw(13800000001 18700000001);
foreach (@mobilelist){
my $mobile = $_;
print "$mobile\n";
#system($sendAlarmcmd); 执行系统命令
}
4.其他:unless,until,for等等
Perl模块
Perl模块有两种来源:一是随Perl发行版本一同打包的;另一种需要用CPAN下载。(CPAN网站:
http:search.cpan.org)
1.手动安装模块
perl Makefile.PL;
make install;
如果没有权限安装模块到全局目录,则可以在Makefile.PL后面加上PREFIX参数,如下:
perl Makefile.PL PREFIX=/Users/fred/lib;
有些Perl模块的开发者会要求使用另一个辅助模块Module::Build来编译并安装他们的作品。此时安装的
方式大致如下:
perl Build.PL;
./Build install;
2.使用CPAN模块自动安装:
在命令行启动CPAN.pm,在其中运行相关模块的维护命令:
perl -MCPAN -e shell;
另一种更简单的方法:
cpan Module::CoreList LWP CGI::Prototype;
CoreList为想安装的模块名称列表
3.使用简单模块
以取得basename为例
use File::Basename;
my $name="/usr/local/bin/perl";
my $basename=basename $name; #返回'perl'
有时候引入的模块中有与自己写的子程序相同的函数名,为避免此冲突,只需在File::Basename的use声
明中,加上导入列表来指明它提供哪些函数。
use File::Basename qw/ basename /;
use File::Basename qw/ /; #表示完全不需求引入任何函数
use File::Basename(); #同上,简写
做完以上声明之后,可以通过全名的方式调用相应的函数
use File::Basename qw/ /;
my $name="/usr/local/bin/perl";
my $dirname=File::Basename::direname $name;
File::Spec模块
File::Spec是面向对象的模块,调用其中的方法,方式如下:
use File::spec;
my $new_name = File::Spec->catfile($dirname,$basename); #模块名称+瘦箭头+方法名称
rename($old_name,$new_name) or warn "Can't rename '$old_name' to '$new_name':$!";
DBI模块
use DBI;
$dbh = DBI->connect($data_source,$username,$password); #连接数据库
$sth = $dbh->prepare("select * from foo where bla"); #准备查询
$sth ->execute();
@row_ary = $sth->fetchrow_array;
$sth->finish
$dbh->disconnect(); #断开数据库连接
sub connectDB
{
print "start connect!\n";
while(!defined ($DB = DBI->connect("DBI:mysql:$Database:$dbIP", "$loginname", "$password"))){
sleep(1);
print STDERR "Couldn't connect the mysql database xx and try it again.\n";
}
print "end connect !\n";
}
---------------------代码块---------------------------
文件头:
use strict; #严格检查语法
use Time::Local;#时间
use POSIX qw(strftime);
use Getopt::Std;
use Net::FTP;
use DBI;#数据库
use MIME::Base64;
use Time::HiRes qw(gettimeofday);
计算时间差:
my($start_sec, $start_usec)=gettimeofday();
doSomething($param);
my($end_sec, $end_usec)=gettimeofday();
my $times_use = ($end_sec - $start_sec)*1000000+($end_usec - $start_usec);
FTP下载:
$ftp = Net::FTP->new("$ftpIP", Timeout => 10) or next;
$ftp->login($user,$passwd) or next;
$ftp->ascii;
$ret = fileDown($ftp, $show);#文件下载
$ftp->quit;
sub fileDown()
{
my ($ftp, $toDir, $cnum) = @_;
my ($curDir, $file,$downfile,$cmd, $pos, $fileNamePre);
$downfile = $toDir."/Data";
$ftp->cwd($downfile) or return -1;
$curDir = $ftp->pwd;
$fileNamePre="a_9101_".$toDir."_".$tdatetime;
my @allfiles = $ftp->ls() or return 0;
foreach (@allfiles)
{
$file=$_;
$pos = -1;
if( index($file, $fileNamePre)==0 && index($file, ".dat")>0 )#搜索.dat文件
{
$ftp->get($file);
$cmd = "mv $file ftpdata/".$cnum."_".$file;#下载文件移到固定文件夹下
system($cmd);
}
}
$ftp->cwd("../..");#不知道这句是要干什么用
return 1;
}
#!/usr/bin/perl -w
#转载简单使用
use Net::FTP;
$server = '192.168.1.251';
$port = '9999';
$user = 'user';
$pw = '123456';
$ftp = Net::FTP->new($server, Port=>$port, Debug => 0, Timeout => 600) or die "Cannot connect.\n";
$ftp->login($user, $pw) or die "Could not login.\n";
$ftp->cwd('/opt/ftp/123') or die "Cannot change working directory.\n";
$remotefile = '123456.mp3';
$localpath = '/usr/local/src';
$localfile = $localpath . "/1234567890.mp3";
$ftp->get($remotefile, $localfile) or die "Could not get remotefile:$remotefile.\n";
print "get file sucessful.\n";
$ftp->quit;
获取时间:
sub GetTTime
{
my $days = (defined $_[0]?$_[0]:0);
$days = ($days*24*60*60);
my ($year, $month, $day);
my @array_date;
@array_date = localtime(time-$days);
$year = 1900+$array_date[5];
$month = $array_date[4] +1;
if ($month <= 9) {
$month= '0'.$month;
}
$day = $array_date[3];
if ($day <= 9) {
$day = '0'.$day;
}
return ($year, $month, $day);
}
判断文件是否存在
sub IsExecOrNot()
{
my $date = $_[0];
my $datefile = "../log/test_$date.log";
my ($ret, $touchfilecmd, $LOG);
$touchfilecmd = "touch $datefile";
$ret = open($LOG, $datefile);
if ($ret){
writelog("open $datefile OK, the script is execed!\n");
close(LOG);
exit;
}
else{
writelog("open $datefile error, the script isn't execed!\n");
system($touchfilecmd);
}
}