一:基础
1:安装perl
centos: yum -y install perl
官网:https://www.perl.org/
升级到5.22:先下载,执行./install.sh 安装
报错:/lib64/libc.so.6: version `GLIBC_2.14' not found (required by perl/bin/perl)
原因:编译时写死了glibc的版本,而系统中只到2.12 ,所以重装glibc即可
解决:查看glibc版本:rpm -qa |grep glibc
下载2.14版本:http://ftp.gnu.org/gnu/glibc/ (官网;http://www.gnu.org/software/libc/)
安装:目录下创建:mkdir build && cd build && ../configure --prefix=/opt/glibc-2.14
make -j4 && make install
增加环境变量:export LD_LIBRARY_PATH=/opt/glibc-2.14/lib:$LD_LIBRARY_PATH
建软链:mv /lib64/libc.so.6 /lib64/libc.so.6.back && ln -s /opt/glibc-2.14/lib/libc-2.14.so /lib64/libc.so.6
安装perl,替换软链: mv /usr/bin/perl /usr/bin/perl.5.10 && ln -s /opt/ActivePerl-5.22/bin/perl /usr/bin/perl
安装过程中提示有文件找不到,创建它即可
2:第一个perl脚本
创建文件:vim helloword
#!/usr/bin/perl
print "Hello , world!\n";
给权限: chmod a+x helloword
运行: ./helloword
3:数据类型
1):数字( perl中的数字都以浮点数值使用)
#!/usr/bin/perlprint 1.2;print 2.000;print -3;print -1.2E22;print 12_321_435;#数字,方便查看print o 377; #八进制print ox ff; #十六进制print ob 11111111;#二进制print 2+2;print 2-1.2;print 1.2 - 3.3;print 1/3; #内部使用双精度计算print 1.0/3;print 1/2.0;print 10%3;print 3**3;
2):字符串(使用utf8编码,文件也须要保存为utf8格式)
#!/usr/bin/perluse utf8; #使用utf8字符集binmode(STDIN, ':encoding(utf8)'); #使用utf8输入binmode(STDOUT, ':encoding(utf8)'); #使用utf8输出binmode(STDERR, ':encoding(utf8)'); #使用utf8输出错误print 'gbz is good\n'; #使用单引号的字符常量print "gbz is good\n"; #使用双引号的字符常量print "\x{2744}"; #双引号的常量自动转义#perl中的操作符跟据运算符号判断须要的是什么类型的值,并会自动转换print "he" . " gg\n"; #.连接符print "he" * 5 ."\n"; #*算数运算,把he转为数字为0print "33he" * 2 . "\n"; #33he转为数字为33print "he" x 4.8; #x字符串复制倍数print "he" . 3 * 4 ; #先算数运算,在字符运算
3):打印错误信息
#!/usr/bin/perl -w 打印简单错误信息use diagnostics; #打印详细错误信息
4):变量( 未定义表示undef)
#!/usr/bin/perluse utf8$age = undef;$age2 = undef; print $age += 1; #与数字运算时,表示0 print "gbz" . $age2 . "gbz"; #与字符运算时,表示空串print defined(undef); #判断是否为undef,是:空,否:1$name = "gbz"; #变量名要有意义$name_length = length($name); #包括字母下划线等print $name;print " ${name} is size : $name_length\n"; #字符串中引用尽量使用${}$ord_name = ord($name); #一个字符转换为码值print $ord_name . "is " . chr($ord_name); #码值转字符
5)运算符
#!/usr/bin/perl
use utf8; #字符比较符:eq,ne,lt,gt,le,ge #数字比较符:==,!=,< ,> ,<=,>= print '1' eq '1'; #字符串比较,true 返回1 print '2' eq '1'; #字符串比较,false 不返回 print 1 == 1; #数字比较 print 2 == 1;
$name = '\n'; if(''|0|'0'|$name){ #假:空,数字0,字符0 print 'true'; }else{ print 'flase'; }
$line = <STDIN>; #用户输入流,以回车结束 if($line eq "\n"){ print "this is blank!\n"; }else{ print "not blank: $line"; }
chomp($line); #去掉末尾回车符,返回1,否则返回0 chomp($line2 = <STDIN>); #先去掉回车,再赋值给变量 print $line2; $line3 = <STDIN>; print chomp $line3; # perl方法可以不用括号
$count = 0; while($count < 10){ $count += 2; print "${count}\n"; }
6):列表和数组
#!/usr/bin/perl
use utf8;$list[0] = 1; #数组从0开始 $list[1] = '2'; #可以存放不同类型的值 $list[100] = 100; #创建了101个元素,中间的值为undef print $list[0] . '--' . $list[100] . '--' . $list[50] . '--'; print $list[1.22]; #下标去掉小数 print $list[-1]; #最后一个 print "\n"; $list = 111; print $list; #与数组同名的变量,与数组是不相关的两个变量 print $list[-22]; ($array11,$array12,$array13) = (1,2,3); #列表创建及赋值 ($array21,$array22) = (1..6); #..范围操作符,把前两个元素赋值 $array3 = qw ( 1 2 3 ); #使用qw 创建数组 $array4 = qw / 1 2 3 4 '1'/; print $array11; print $array22; print $array4; #返回最后一个元素 @array = (1.2..5.6); #小数会转换成整数 print @array; #@表示整个数组 print pop @array; #取出末尾一个元素 push @array,1..3; #把1,2,3放到@array末尾 print @array; print shift @array; #取出第一个元素 unshift @array,1; #把1放到开头 splice @array,1,2,qw(22); #从索引1开始,取出两个元素,用22替换 $_ = '44'; #$_是perl的默认变量,是全局变量 foreach $_ (@array){ #在循环中$_是局部变量,与全局变量占用不同的存储空间 print $_ . "\n"; } print $_;#循环外打印的是全局变量的值 print reverse 1..6; #倒序 print sort 5..10,'ss',' ',"\n"; #unicode码值顺序
7):map(哈希)
perl中标量,列表,哈希都有各自的命名空间,即使同名也不影响
map中 key可以是 数字,字符串,undef;但都会转为字符串
map中 value可以是 数字,字符串,undef,列表等
创建和取值:
$map{'name'} = 'gbz';
$map{ age} = 25; #key自动转为字符串 $map{1} = undef; $map{undef} = 1; 取值:print $map{undef} ;
删除:delete $map{name};
key是否存在:print exists $map{names}; #存在:1 ,不存在:undef
访问整个map
print %map;
转换
list ==>map : %map = (' name',"gbz",' age',25); #(key , value , key , value)
map ==>list: @array = %map;
胖箭头:%map = ('name' => "gbz",'age' => 25); #perl自动把=>转换为,
keys values
%map = ('name' => "gbz",'age' => 25);
@k = keys %map; #得到所有key
@v = values %map; #得到所有value
遍历
while( ($key , $value) = each %map ){
print " $key ==> $value"; }
读取环境变量:print "home is $ENV{ HOME }\n";
4:标量上下文和列表上下文(重点)
在perl中跟据上下文不同,得到的结果也不同:
@ list = qw ('g','b','z');
@array = sort @list; #列表上下文,得到的是g b z
$size = 42 + @list; #标量上下文,得到的是45
区分标量还是列表主要查看表达式须要什么类型的数据
在列表上下文中使用产生标量的表达式:产生一个元素的列表
@list = 6*7; # (42)
强制指定标量上下文:print scalar @list; #得到的是元素个数
列表上下文中的stdin:@lists = <STDIN>; 返回返有行,直到末尾
标量上下文中的stdin:$list = <STDIN>;返回下一行数据
5:子程序(方法或函数)
#!/usr/bin/perluse utf8;#use strict; #use 5.012 严格编译检查,建意开启sub max {$n += 1; #perl默认变量都是全局变量print "number is $n\n";}&max; #调用自定义方法&max;sub max { #会覆盖同名方法,此时上面的两个调用的也是被覆盖的方法print "~~~~";}max; #如可没有和perl内置方法重名可以省略&号调用方法sub number {$n = 0;$n + 3; #默认子程序返回值为最后一句代码的值}print &number;sub return_sub {1 + 1;return 22; #可以返回列表,标量,undef; return ; 一般表示程序执行有误1 + 2;}print return_sub;sub unmber_max {my($m,$n) = @_; #my()用来定义私有变量,与方法外同名变量互不影响if ($_[0] > $_[1]){ #perl使用@_来接收参数,是私有变量$m; #也会使用$_[index]数组来接收参数}else{$n;}}print &unmber_max(19,30);use 5.010; #foreach须要设定版本才可使用sub addlist {state @lists; #私有变量,其值会被保存下来,留给下一次子程序执行时继续使用foreach my $l (@_){push @lists,$l;}say "this list @lists";}addlist(1..4);addlist(2,7);say @lists; #方法外不能访问state 定义的变量
6:输入与输出
1)读取标准输入(while会一行一行的读;foreach会读入全部,效率低下)
while (defined($line = <STDIN>)){
print "I saw ${line}\n"; } //简写 while (<STDIN>){ print "I saw $_\n"; }
2)钻石操作符输入(<STDIN>的简写)
3)标准参数(@ARGV,我们可以修改它)while (<>){chomp; #默认去掉$_后的换行符print "I saw $_\n";}调用:./io io #读取“文件io”到标准输入流
4)标准输出(<STDON>)调用: ./io sub默认参数存放到 @ARGV 中, <STDIN>依次读取@ARGV中的数据
5)文件句柄 命名:一般大写print("out print str"); #输出到标准输出流print "out print str"; #简写,去掉括号print (2+4)*4; #print (2+4)输出成功返回1,再乘4printf "hello , %s; in %d days!\n" ,"gbz" , 3; printf "%g %g %g \n" , 5/2 , 31/17 , 22**33; #数字原样输出 printf "截断,只保留整数部分 %d \n" , 22.334; printf "||% 6d||% -6d||\n" , 33 , 55; #正6左补空格,负6右补空格 printf "||%12 .3f||\n" , 43.23525; #保留3位小数 printf "%.2f%%\n" , 22.45; #百分号use 5.010;say "gbz" ; #自动换行功能my @list = qw (22.34 11.542 11.667); printf "the items are:\n" . ("%10.1f\n" x @list), @list; #相当于%10.1f\n %10.1f\n%10.1f\n# ("%10.1f\n" x @list) 标量上下文,@list为元素个数
perl默认的文件句柄:STDIN、STDOUT、STDERR
打开文件的方式 : open CONFIG, 'io'; #读写方式打开文件,使用CONFIG访问 open CONFIG, '<io';#只读方式打开文件
open LOG, '>test.io';#覆盖写入文件
open LOG, '>>test.io';#追加
更好的方式:
open CONFIG, '<' , 'io';#只读方式打开文件
open LOG, '>' , 'test.io';#覆盖写入文件
open LOG, '>>' , 'test.io';#追加
指定编码:(查看perl支持的:perl -MEncode -le "print for Encode->encodings(':all')")
open CONFIG, '<:encoding(UTF-8)' , 'io';
或:open LOG, '>:utf8' , 'test.io';
一劳永逸(指定所有输入为utf8):binmode STDIN, ':encoding(UTF-8)';
有问题的文件句柄:
open 命令打开文件成功:返回真
失败:返回假
输出错误:
终止程序:die "error : $!"; #perl默认使用$!存放错误信息,会放到标准错误流中
不终止:warn "error : $!";
自动检错:use autodie;
关闭句柄:(perl会在程序关闭或重新使用前关闭句柄)
close LOG;
使用文件句柄:
open CONFIG, '){ chomp; print $_;}
改变输出句柄:
select LOG; #默认输出现在为LOG
$| = 1; #不缓冲直接输出
select STDOUT; #还原
重定向句柄失败后,perl还使用之前的
包柄存到标量变量中:
open my $log_fh, '>','io.txt' or die "error : $! \n"; #打开文件,有错误会报错 print { $log_fh} "gbz"; #输入到文件中 while (<$log_fh>){ #读取,'>' 换成 ‘<’ chomp; print $_; }