Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31067
  • 博文数量: 11
  • 博客积分: 265
  • 博客等级: 入伍新兵
  • 技术积分: 105
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-26 00:54
文章分类

全部博文(11)

文章存档

2011年(11)

我的朋友

分类: Python/Ruby

2011-10-21 13:30:48

第八章 正则表示式

1)
=~: 匹配为真,没有匹配为假
=!: 不匹配为真,匹配为假。

对数组匹配 grep (/abc/,@a);
split(/abc/,$line)根据模式匹配分割字符串

模式匹配的3中类型:
m//模式匹配, s///匹配并替换, tr///逐一替换,翻译

2)字符匹配
+    一个或多个相同的前导字符 
*    0个、1个或多个相同字符
?   0个或1个
.     匹配除换行外地所有单个字符
{}   匹配指定数目的字符

3)模式匹配:选择
[]    匹配一组字符中的任一个
[^]   表示除其之外的所有字符

/^-?\d+$/: 匹配十进制数字
/^-?0[xX][\da-fa-F]+$/ : 匹配十六进制数字

4)  转义符和定界符
\:  转义符
\d 任意数字[0-9]    \D 除了数字以外的任意字符
\w 任意单词字符[_0-9a-zA-Z]      \W   任意非单词字符[^_0-9a-zA-Z]
\s 空白 [\r\t\n\f]               \S非空白[^\r\t\n\f]

定界符:
 ^或\A 仅匹配字符串首            $或\Z 仅匹配字符串尾
 \b 匹配单词边界                    \b 单词内部匹配
 
5)模式的重用
  \n  来多次引用 : 把匹配的值存起来以后使用。
 /\d{2}([\W])\d{2}\1\d{2}/  匹配12-05-92  但不匹配 12-05.92

6)模式变量
在模式匹配后调用重用部分的结果可用变量$n,全部的结果,匹配模式用变量$&,包含不在括号中的。匹配
处之前的部分用变量$`,匹配处之后的部分变量用$'。也可用列表一次取得。
  $string = "This string contains the number 25.11.";
  $string =~ /-?(\d+)\?(\d+)/;   #匹配结果为25.11
  $integerpart = $1;  #now $integerpart=25
  $decimalpart = $2;  # now $decimalpart = 11
  $totalpart = $&; #now totalpart=25.11
  @result =~ /-?(\d+)\.?(\d+)/;

7)匹配选项
  g 匹配所有可能的模式
  匹配的循环:每次匹配记住上次的位置
  while("balata" =~ /.a/g) {
     $match = $&;
     print ("$match\n");
  }
  结果
   ba
   la
   ta
  当要匹配的字符串改变时重新开始搜索
  当使用了选项g时,可用函数pos来控制下次匹配的偏移
    $offset = pos($string);  下一个匹配开始的位置;
    pos($string) = $newoffset;  从此位置开始搜索匹配

i   忽阅模式中的大小写
m  将待匹配串视为多行
s   将待匹配串视为单行
o   仅只执行一次变量替换
x   忽阅模式中的空白

8)匹配符号的优先级
()   模式内存
+ * ? {}   出现次数
^ $ \b \B 
| 选项

9) 扩展匹配模式
(?pattern)  其中c是一个字符,pattern时起作用的模式或子模式
1、(?:pattern)不存储括号内的模式匹配内容
如/(?:a|b|c)(d|e)f\1/中的\1表示已匹配的d或e,而不是a或b或c。

2、 /(?option)pattern/内嵌模式选项
  通常模式选项置于其后,有四种选项:i、m、s、x可以内嵌使用,等价于/pattern/option
如/(?i)[a-z]+/ = /[a-z]+/i

3、(?#注释)模式注释
if ($string =~ /(?i)[a-z]{2,3}(?#match two or three alphabetic characters)/
{....}

4、(?)取消贪婪
"a12b38b"  /a.*/ 全部匹配,当/a(.*?)b/时匹配a12b
同样有*?,+?,??,{x}?,{x,}?,{x,y}?

5、/pattern(?=string)/肯定的和否定的预见匹配  ?= ?!
例题1
$line="block1 first block2 second block3 third";
$line =~ /block\d(.*?)(?=block\d|$)/g;
print $1;
例题2 使用while
$line = "begin begin begin ";
while($line=~ /begin(.*?)(?=begin|$)/sg)
{push(@blocks,$1;}


10)替换操作
s/pattern/replace/

替换操作符的选项:g,i,m,o,s,x,e
e 替换字符串作为表达式
$string = "0abc1";
$string =~ s/[a-zA-Z]+/$& x 2/e;
#now $string = "0abcabc1"


11)模式定界符
模式定界符为反斜线/,但其可用字母m自行指定,
m!/u/jqpublic/perl/prog1! 等价于/\/u\/jqpublic\/perl\/prog1/
quotemeta('ab') = \a\b 自动加反斜线





第九章:格式化输出

1)格式的使用
将系统变量$~设成所要使用的格式,调用函数write。

 #!/usr/bin/perl
 $~ = "MYFORMAT";
 write;

 format MYFORMAT =
 ===================================
 Here is the text I want to display.
 ===================================
 .

2)输出到其他文件
write将结果输出到STDOUT,输出到任意其他的文件中有两个方法:
1、write(MYFILE)
这样,write就用缺省的名为MYFILE的打印格式输出到文件MYFILE中,但这样就不能用$~变量来改变所使用的打印格式。系统变量$~只对缺省文件变量起作用。
2、改变缺省文件变量,改变$~,再调用write,例如:
select(MYFILE);
$~="MYFORMAT";
write;

3)格式控制符
@<<<  左对齐输出
@>>>  右对齐输出
@|||   居中对齐输出
@##.###  固定精度数字
@*      多行文本
format MYFORMAT =
===================================
   Here is the text I want to display.
===================================
.

open(F,"quote");
@quotation = ;
close(F);
$quotation = join("",@quotation);
$~ = "QUOTATION";
write;

format QUOTATION =
Quotation for the day:
-------------------------
~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$quotation
~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$quotation
~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$quotation
-------------------------
.



format QUOTATIONS =
Quotation for the day:
-------------------------
~~   ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$quotation
-------------------------
.


3)分页
页眉:filename_TOP的格式表示页眉,例如给标准输出文件定义页眉:
format STODOUT_TOP =
Consolidated Widgets Inc. 1994 Annual Report

在页眉的定义中也可以包含格式,如当前页码,存储在$%中,如:
format STDOUT_TOP =
Page @<<.
$%
.

$^改变定义页眉的打印格式名,$^只对当前缺省文件起作用
$=每页的长度  缺省每页长度为60行,$=  =66;#页长设为66行
$-当前行到页末之间的行数,当$-达到0时, 就开始新的一页。

分页时不用print函数,当用write输出时,perl解释器跟踪每页的当前行号,对print不计算。如果使用print就会使行过长,可以调用系统变量$-.
print("Here is a line of output\n");
$- -=1;


4)printf函数



第十章  函数

1)子程序(函数)定义
带有原型说明的子程序定义:
  sub subroutine ($$) {   #需要两个简单变量的参数
      statements;
  }
()中的符号表示参数的类型。以一个字符表示参数。
$简单变量      @列表       %散列
&匿名子程序              *引号
前加\为强制类型一致。  ;分隔必须的参数和可选参数。
\@$;$ 表示第一个参数为列表,第二个参数为简单变量,第三个参数简单变量可选。

2)使用别名或引用传递数组
用别名的方法可以传递多个数组,并能区分数组分界。如:
@array1 = (1,2,3);
@array2 = (4,5,6);
&two_array_sub(*array1,*array2);
sub two_array_sub {
  my(*subarray1, *subarray2) = @_;
}
在该子程序中,subarray1是array1的别名,subarray2是array2的别名。

引用:不要对同名变量生效
&two_array_sub(\@array1,\@array2);
sub two_array_sub {
  my ($subarray1, $subarray2) = @_;
}
引用是简单变量。要传递给简单变量。
使用引用@$subarray1。$subarray[1]->[0]。


#!/usr/bin/perl
print "1.函数可放在任何地方。\n";
while (1) {
  &readaline;
  last if ($line eq "q\n");
  sub readaline {
    $line = ;
  }
  print ($line);
}
print ("done\n");
<>;


print "2.用别名传递\n";
$foo = 26;
@foo = ("here's","a","list");
&testsub (*foo);
sub testsub {
  local (*printarray) = @_;
  $printarray = 61;
}
print "$foo\n";
<>;

3)调用子程序
1、&标准调用:&subname(1,2);
  无论子程序定义在什么地方都可以用&调用子程序。
2、常用调用:subname(1,2);
  只有在调用之前已经定义的子程序才可以省略&
sub subname{} ... subname;
3、前向引用:先声明,再调用,在定义
  sub  subname;
  subname(1,2);
  sub subname{...}
4、用do调用: do subname(1,2);相当于&subname(1,2);
5、引用: &$subref(1,2); &不能省略。
6、子程序调用可省略():subname(1,2)   subname 1,2。但可能引起优先级问题。


4)递归调用
子程序可以互相调用,当调用子程序本身时,即成了递归子程序。
递归子程序有两个条件:
  1、除了不被子程序改变的变量外,所有的变量必须是局部的。
  2、该子程序要含有停止调用本身代码。
print "4.递归\n";
sub f{
  my $a = shift;
  $a==1?1:$a*f($a-1);
}
print f(10);

5)预定义的子程序
perl5预定义了三个子程序,分别在特定的时间执行,你可以自己定义它们,以特定时间执行所需的动作:
BEGIN子程序在程序启动时呗调用;
END子程序在程序结束时被调用;
AUTOLOAD子程序在找不到某个子程序时被调用。

BEGIN {
  print("Hi! Welcome to Perl!\n");
}
AUTOLOAD {
  print("arguments password: @_\n");
}



第十一章   引用
1)引用的创建
用\创建变量
简单变量的引用:$var = 22;$ref = \$var;连续引用:$rr=\\$var,访问$$$rr;
常量的引用:     $ref=\3.14;
数组的引用:     $ref=\@ARGV;
散列的引用:     $ref=\%ENV;
函数的引用:     $ref=\&func;  (func的定义在其他位置),不要(),当\$func()时为执行函数,返回值再引用。
文件的引用:     $ref=\*STDOUT;
匿名数据的引用:$ref=[1,2,['a','b']];
匿名散列的引用:$ref={'a'=>1,'b'=>2};
匿名函数的引用:$ref=sub{print "anonymous func";}   不用函数名
每个变量都有引用计数,有引用指向的变量计数增加。最初引用的变量销毁了,引用仍可使用:
{ my $a ="hello world"; $a=\$a;} print $$a;
创建a时引用计数为1,$ra引用后计数为2,超出作用域后a销毁,计数为1,内存未回收。引用和变量要同时销毁(超出作用域)或把引用赋与一个值,循环引用无法释放内存。
 #!/usr/bin/perl

 print "1.引用的变量销毁,仍可引用\n";
 {
   my $ra;
   {
     my $a = "hello world";
     $ra = \$a;
   }
   print "ref=$$ra a = $a\n";
 }
 print "ref=$$a\n";

2)引用的使用
简单变量:    $$ref  ${$ref}
数组:         @$ref   @{$ref};    元素:$$ref[0]  $ref->[0];
散列:    %$ref    %{$ref}     元素:$$ref['a']  $ref->['a']
函数:  &$ref(a,b)     $ref->(a,b)
文件: $ref

${}内部可以是表达式,结果为$ref
->只用于非简单变量
引用可相互赋值:  $ref1=$ref
引用会改变指向的变量的值:$a=1;$ref=\$a;$$ref++->$a=2
引用可还原为普通变量:$ref=1;

3)Ref()与引用的显示
ref($a):如果$a不是引用为假,时引用为真。值如下:
SCALAR   简单变量的引用
ARRAY  数组的引用
CODE 代码(函数)的引用
REF 引用
GLOB 类型通配

print $ref返回类型+地址   HASH(0x809C09D)

4)类型通配typelob
包的全局变量存在一个符号表中,可查找和定位。每个变量一个入口,每个入口包含所有类型的名字,如$name,@name,%name,&name,文件name,格式name。这个入口名为类型通配*name。代表所有的类型。
  也可将类型通配看成一个散列,关键字为类型SCALAR,ARRAY,值为变量(入口的变量名为散列名name,name{ARRAY}=@name)。则*name{SCALAR}为$name的引用,使用可$$name或${*name}、@{*name}
  类型通配可以赋值。*newname=*name,则newname的变量成为name的变量的同义词。一个变量有两个名字,$name也是$newname。

5) 类型通配的应用
  1、创建常量变量: *PI=\3.14;再修改PI时$PI=3;产生错误。
  2、匿名结构起名:my $anony=[1,2,3]; *name=$anony; print @name;
  3、引用文件句柄:把类型通配(其中包括文件变量)赋给简单变量,在文件上下文使用。
      my $out=*STDOUT;  print $out 'name';
      函数中传递文件句柄:
  把文件名传递进去,在函数内重新打开。
  将类型通配传入,$f=*STDOUT;func($f);整个类型通配传入。
  先得到类型通配的引用,再将引用传入。
    my $out=*STDOUT;$f=\out;func($f); ===>$f=\*STDOUT;
  4、只改变简单变量: *newname=\$name.   $name和$newname一样,是别名。但@newname,@name不       一样
  5、做为函数参数传递时类型通配最快,但对类型通配操作可改变变量的值。
      foreach $f(10,20,30) {foo(*f);}
      sub foo{local (*g)=@_;$g++;}  出错,对常量10自增

print "2.作用域外地局部变量\n";
sub generate_greeting {
  my($greeting) = "hello world";
  return sub {print $greeting};
}
$rs = generate_greeting();
&$rs;

sub generate_greet {
  my($greeting) = @_;        # $greeting primed by arguments
  return sub {
    my($subject) = @_;
    print "$greeting $subject \n";
  }
}
$rs1 = generate_greet("hello");
&$rs1("world");







sub even_number_printer_gen {
  my($input) = @_;
  if($input%2) {$input++};
  $rs = sub {
    print "$input ";
    $input += 2;
  };
  return $rs;   #Return a reference to the subroutine above
}
$iterator = even_number_printer_gen(31);
for ($i=0; $i<10; $i++) {
  &$iterator();
}
print "\n";




第十二章 Perl包和模块

1)符号表
包的变量和子程序存在符号表中。
在程序中查找符号表可用数组%package::,package为符号表所属包名,查到的是变量名。
$main::{$key}变量名
${$main::{'a'}}得到变量$a的值。

#!/usr/bin/perl

$a = 1;
$b = 2;
foreach $key (keys %main::)
{
  print "\$$key => $main::{$key}\n";
}
print ${$main::{'a'}};
print "\n";




package sep_test;
my $sep = ' ';

sub set_sep {  #设置分隔符,返回診055来的分隔符
  my $prev_sep = $sep;
  if (@_) {$sep = $_[0] }
  return $prev_sep;
}
sub flip_words {
  my $line = $_[0];
  my @words = split($sep,$line);
  return join($sep, reverse @words);
}

package main;
$line = "a:b:c";
$sep_save = sep_test::set_sep(':');
print sep_test::flip_words($line);
print "\n";


2)模块定义
多数大型程序都分割成多个部件,每一个部件通常含有一个或多个子程序及相关的变量,执行特定的一个或多个任务。集合了变量和子程序的部件称为程序模块。
perl5中用包来创建模块,创建包并将之存在同名的文件中。
如:名为Mymodule的包存储在文件Mymodule.pm中
package Mymodule;
require Exporter;
@ISA=qw(Exporter);
@EXPORT= qw(myfunc1 myfunc2);
@EXPORT_OK=qw($myvar1 $myvar2);
sub myfunc1 {$myvar1 +=1;}
sub myfunc2 {$myvar2 +=2;]
1; 
前面时模块通常包含的声明,后面是变量和函数的定义。












































阅读(1216) | 评论(0) | 转发(0) |
0

上一篇:perl用法

下一篇:perl用法

给主人留下些什么吧!~~