Home > fundamental > perl 学习笔记

perl 学习笔记

看《perl 语言入门第四版》时的笔记,perl实在是太灵活了,只简单记录了些个人感觉常用的,又比较重要的地方。

  1. 数组

$#rocks代表$rocks[N]最后一个索引,即N。所以可以将$#rocks看成@rocks的记录数-1。

负数值的索引号代表从最后开始,$rocks[-1]=$rocks[$#rocks]=$rocks[N],超出范围会报错。

@rocks  #all of the rocks

@rocks跟context有关,比如print “@rocks\n”;输出所有元素值,$t=@rocks;这里$t就等于@rocks的个数。

Scalar函数:强制转换list-producing为scalar-producing,如print “the number is :”,scalar @rocks,”\n”;

数组赋值可以这样:

@rocks=qw/a b c d e/

@tiny=() #空数组

@giant=(1..100)

@small=(1,2,3,4)

@medium=(1,2,3..5,6) @即1到6

@ok=(@gaint,@small,undef) #105个值

pop 操作将数组的最后一个元素取出并返回:

@array = 5..9;

$fred = pop(@array); #$fred 得到9,@array 现在为(5,6,7,8)

$barney = pop @array; #$barney gets 8, @array 现在为(5,6,7)

pop @array; #@array 现在为(5,6)(7 被丢弃了)

   push(@array,0); #@array 现在为(5,6,0)

push @array,8; #@array 现在为(5,6,0,8)

push @array,1..10; #@array 现在多了10 个元素

@others =qw/9 0 2 1 0 /;

push @array,@others; #@array 现在又多了5 个元素(共有19 个)

同理,shift跟unshift控制数组开始部分。

Foreach控制结构#类似于for

      foreach $rock (qw/ bedrock slate lava /){

print “One rock is $rock.\n”; #打印出3 种rocks

}

等价于
foreach (qw/ bedrock slate lava /){

print “One rock is $_.\n”; #打印出3 种rocks

}

 

@rocks = qw/ bedrock slate lava /;

foreach $rocks(@rocks){

$rock = “\t$rock”; #@rocks 的每一个元素前加入一个tab

$rock . = “\n”; #每一个元素后加一个换行符

}

print “The rocks are:\n”,@rocks; #每一个元素都被缩进了,并且一个元素占一行

   reverse 操作

           @fred = 6 ..10;

@barney = reverse (@fred); #得到10,9,8,7,6

@wilma = reverse 6 ..10; #同上,没有使用额外的数组

@fred = reverse @fred; #将逆转过的字符串存回去

print操作

print @lakers跟print “@lakers”是不同的,如果@lakers=qw /a b c/,则前者输出abc,后者输出a b c.

  1. 子程序(subroutines)

语法:

sub xxx{}

定义私有变量:my如my($m,$n)=@_;my($t)=$_;

私有变量不局限于子程序,在任何程序模块中均可,比如foreach的循环中。

需要注意的是:my操作不会改变赋值参数的context.

                  my ($num) = @_; #列表context, 同($sum) = @_;

my $num = @_; #标量context,同$num = @_;

例如:

#!/usr/bin/perl -w

#use strict;

$lakers=125;

$bull=111;

$result=&cal($lakers,$bull);

print “the result is :\n$result\n”;

sub cal{

my($la,$bu)=@_;

if($la>$bu){return “LA Wins!”}

else {

if($la<$bu) {return “BU Wins!”}

else {return “DRAW!”;}

}

}

运行结果:

[root@qifeng1 root]# perl t.pl

the result is :

LA Wins!

 

调用子程序时使用的&符号表明让编译器先寻找子程序的声明。所以如果调用perl自带的内嵌函数可以不用&,如chomp();如果将sub xxx{}声明写在调用之前并且可以保证perl中没有xxx的内嵌函数那么调用时也可以省略&符号。但如果想自定一个chomp函数或者函数声明写在调用之后,那调用时需加上&符。

子程序也可以返回列表值,如:

sub list_from_fred_to_barney {

if($fred < $barney) {

#Count upwards from $fred to $barney

$fred ..$banrey

} else {

#Count downwards from $fred to $barney

reverse $barney ..$fred;

}

$fred = 11;

$barney = 6;

@c = &list_from_fred_to_barney; #@c 为(11,10,9,8,7,6)

  1. 输入与输出

printf“The items are:\n”. (“%10s\n”x @items), @items;

@ARGV数组记录了参数列表,需要注意的是程序名不存在$ARGV[0]当中,而是由$0这个变量存储。

$line = <STDIN>; #读入下一行;

chomp($line); #去掉结尾的换行符

chomp($line=<STDIN>) #同上,更常用的方法

while (defined($line = <STDIN>)) {

print “I saw $line”;

}

等价于

while(<STDIN>){

print “I saw $_”;

}

 

@argv = qw# larry mor curly #; #在<>操作前可以强制使用这三个文件

while(<>){ #<>操作查看@argv 来决定使用哪些文件。如果表为空,则使用标准输入流;否则,使用其找到的相应文件。

chomp;

print “It was $_ that I saw in some stooge-like file!\n”;

}

  1. 文件句柄
  • open XXX ,”< test.txt”; #打开test.txt作为标准输入文件,句柄为XXX
  • open XXX ,”> test.txt”;
  • open XXX ,”>> test.txt”;

close XXX;

 

if(!XXX){

die “something is wrong!!!$!” #die会终止脚本,$!会输出相关错误信息

}

 

if(!open MSG,”>>msg.log”){

die “WRONG!!!$!”;

 

}

 

print MSG “this is the 1st row.\n”; #指定MSG句柄输出到msg.log

 

select MSG; #select 可以选择默认句柄,默认是STDOUT

 

print “this is the 2nd row.\n”;

print “this is the 3rd row.\n”;

close MSG;

  1. 正则

元字符:

. :匹配任何单个字符

简单量词:

*匹配前一项0次或多次<=>{0,}

+匹配前一项1次或多次<=>{1,}

?前一项要么匹配,要么不匹配<=>{0,1}

{a,b} 匹配前一个字符重复a到b次

{a,} 匹配前一个字符重复至少a次

{a} 匹配前一个字符重复a次

 

分组:

/(haha)+/

选择符:

| or

/fred( |\t)+barry/

字符类

[]

[a-zW-YZ0-9]

[^0-9]匹配0-9以外的任何字符

字符的简写

[0-9]:\d

[A-Za-z0-9_]:\w

[\f\t\n\r ]:\s

对应补集分别是^\d,^\w,^\s或者\D,\W,\S

m//匹配

默认用//匹配可以省略掉m,但是用m%%,m##等一样可以用来正则匹配

可选的修饰符

/i 不区分大小写,如/yes/i可以匹配YES跟yes

/s 可以使.也匹配换行符,在多行匹配中比较有用,类似于[\d\D],如/a.*b/s

/a 如$t=~/xx/a匹配时只编译一次,针对$t不变的情况,特别是$t的值很长的时候可以提高性能,避免每次匹配时都编译一次

锚定

/^abc$/只含有abc的行

/^\s*$/空行

词锚定

\b 匹配单词(这里的单词指\w的范围)

如\bqifeng\b可以匹配 qifeng,”qifeng”等,但不会匹配qifeng2,biti_qifeng等;\bcal可以匹配calvin,但不可以匹配calcal。

绑定操作符

=~ ,指定字符串匹配,而不必是$_

my $lakers=”I miss you.”

if($lakers=~/\bmiss\b/){

print “you got it!\n”;

}

模式的内插

例如:

$who=”angelababy”;

if(/($who)/){…} #这里$who被替换成angelababy

匹配变量

    $_ = “Hello there, neighbor”;

if(/(\S+) (\S+), (\S+)/){

print “words were $1 $2 $3”;

}

自动匹配变量

$& 匹配成功的部分

$` 匹配字符串的前部分

$’ 匹配字符串的后部分

据说这3个使用这3个变量的耗费比较大。。

如:

    if (“Hello there, neighbor”=~ /\S(\w+),/){

pirnt “That was ($`)($&)($’)”;

}#输出:(Hello)( there,)( neighbor)

s///替换

$_ =“He’s out bowling with Barney tonight.”;

       s/with (\w+)/agaist $1’s team/;

print “$_\n”

 

s///g全局替换

s/\s+/ /g 多空格替换为单空格

s/^\s+//g 去掉开头的空格

s/\s+$//g去掉结尾的空格

不同的分隔符

同m//跟qw//一样,s///也可以使用不同的分隔符,如s###,如果是配对的分隔符,可以这样:

s{}{},s{}[],s<>##等

可选的修饰符

出了/g,其他如/s,/i,/x也可以使用,如s/a/b/gi;

绑定操作符

同m//

大小写转换

\U 后面的字符全部大写

\L 后面的字符全部小写

\u 后面第一个字符大写

\l 后面第一个字符小写

\E 取消后面的影响

s/(\w+) with (\w+)/\U$2\E with $1/I; #$1 现在是“I saw FRED with barney.”

s/(fred|barney)/\u\L$1/ig; #$_现在为“I saw Fred with Barney.”

双引号中也可以使用

print “Hello, \L\u$name\E, would you like to play a game?\n”

split

@fields=split /separator/,$string

@fields = split /:/, “:::a:b:c:::”; #得到(“”, “”, “”, “a”, “b”, “c”);

Join

my $result = join $glue, @pieces;

my $x = join“:”, 4, 6, 8, 10, 12; #$x 为“4:6:8:10:12”

非贪婪的数量词

在贪婪数量词后面加+,如.*?、.+?、{5,8}?、{5,}?、??

$_=”this is <h>header1</h>,<h>header2</h>”;

s/<h>(.+)<\/h>/$1/g;

print $_.”\n”;

#输出:this is header1</h>,<h>header2

$_=”this is <h>header1</h>,<h>header2</h>”;

s/<h>(.+?)<\/h>/$1/g;

print $_.”\n”;

#输出:this is header1,header2

  1. Perl 命令行

$perl –p –i.bak –w –e ‘s/qifeng/fuyar/g’ temp*.dat

-p 类似于:

while(<>){

print;

}

-i 指定$^I参数

-w use warnings

-e 执行后面的命令,多个命令可以用多个-e分开

Temp*.dat <>的输入

  1. 非捕捉用的括号

(?:) 即不捕捉括号内的内容,也不会分配内存来存储,也不会分配变量名

例如:

$_=’lakers’;

if(/(?:l).*(s)/){

print “the last letter is $1\n”;

}

#输出:s

  1. 使用简单的模块
    1. File::Basename

常用函数比如basename,dirname

use File::Basename qw/basename/;

 

$_=”/usr/bin/perl”;

my $bname=basename $_;

my $dname=File::Basename::dirname $_;

print “basename:$bname\ndname:$dname\n”;

输出:

basename:perl

dname:/usr/bin

  1. DBI

Perl中貌似没有自带DBI跟DBD模块,所以需要我们自己安装。

安装:

DBI和相应数据库的DBD可以从http://dbi.perl.org/下载,版本需要跟自己的perl版本兼容。

以安装DBD:Oracle为例:

[root@qifeng1 tmp]# whoami

root

[root@qifeng1 tmp]# ls

DBD-Oracle-1.17  DBD-Oracle-1.17.tar.gz  DBI-1.53  DBI-1.53.tar.gz

[root@qifeng1 tmp]# export ORACLE_HOME=/opt/ora10g/product/10.2.0/db_1

[root@qifeng1 tmp]# export LD_LIBRARY_PATH=$ORACLE_HOME/lib:/lib:/usr/lib

cd DBI-1.53

perl Makefile.PL

make

make test

make install

cd DBD-Oracle-1.17

perl Makefile.PL

make

make test

make install

make test DBD的时候,测试结果报错信息如果是不能连接’scott/tiger’类似的可以忽略,如果想test成功可以将报错行的

my( $default, $dsn ) = ( ‘dbi:Oracle:’, $ENV{ORACLE_DSN} );

改成

my( $default, $dsn ) = ( ‘dbi:Oracle:testdb’, $ENV{ORACLE_DSN} );#testdb是tns的服务名。

DBI测试:

#!/usr/bin/perl

 

use DBI;

use warnings;

 

my $conn=”DBI:Oracle:”;

my ($dbh,$sth);

my @result;

print “start to connect…\n”;

$dbh=DBI->connect($conn,”lyn”,”lyn”);

print “connect successfully\n”;

$sth=$dbh->prepare(“select * from users”);

$sth->execute();

while(@result=$sth->fetchrow_array()){

print join(“\t”,@result).”\n”;

}

$sth->finish;

$dbh->disconnect();

exit(0);

输出:

start to connect…

connect successfully

OUTLN   OPEN

SYS     OPEN

SYSTEM  OPEN

PIS     OPEN

LYN     OPEN

DBSNMP  EXPIRED & LOCKED

TSMSYS  EXPIRED & LOCKED

DIP     EXPIRED & LOCKED

Categories: fundamental Tags:
  1. No comments yet.
  1. No trackbacks yet.