现在的位置: 首页 > 综合 > 正文

Perl编程

2013年12月05日 ⁄ 综合 ⁄ 共 7410字 ⁄ 字号 评论关闭

反向模式匹配/[^;]+;/    比如使用 /[^:]+:/,表示匹配一个或多个不是冒号的的字符(也是尽可能多),这样正则表达式匹配至第一个冒号.

/bam{2}/ 将匹配 “bamm”而不是“bambam”。如果你要对多于一个字符使用量词,你需要使用圆括弧,因此为了匹配“bambam”需要使用 /(bam){2}/

^ 和 $ 实际上是用于行的开头和结尾,而不是字符串开头和结尾.

特殊符号 \b 匹配单词边界,就是位于单词字符 (\w)和非单词字符(\W)之间的零宽度的地方字符串的开始和结尾也被认为是非单词字符,
\bFred\b/ 将会匹配 “The Great Fred”和“Fred the Great”中的 Fred,但不能匹配“Frederick the Great” ,因为在“Frederick”中的“d”后面没有跟着非单词字符。

 

/\d+/ 和 /(\d+)/ 仍然会尽可能多地匹配数字。但后边的写法能够把匹配到的数字保存到一个特殊变量中,以供以后反向引用。

   $x = (($a,$b)=(7,7,7));      # 把 $x 设为 3,不是 2
   $x = ( ($a, $b) = funk());   # 把 $x 设为 funk() 的返回数
   $x = ( () = funk() );      # 同样把$x 设为 funk() 的返回数

获取数组个数:@days + 0; # 隐含地把 @days 处于标量环境 scalar(@days) # 明确强制 @days 处于标量环境 请注意此招只对数组有效。

$#days。这样会返回数组里最后一个元素的脚标,或者说长度减一,因为(通常)存在第零个元素。给 $#days 赋值则修改数组长度。
用这个方法缩短数组的长度会删除插入的数值。

要算出一个散列里面的键字的数量,在标量环境里使用 keys 函数:scalar(keys(%HASH)).

双目 =~ 把一个字串和一个模式匹配、替换或者转换绑定在一起

双目 !~ 类似 =~ 操作符,只是返回值是 =~ 的对应返回值的逻辑非。下面的表达式功能上是完全一样的:

   $string !~ /pattern/
   not $string =~ /pattern/

双目 x 是复制操作符
   print '-' x 80;            # 打印一行划线
   print "\t" x ($tab/8), ' ' x ($tab%8);   # 跳过
   @ones = (1) x80;      # 一个80个1的列表
   @ones = (5) x @ones;      # 把所有元素设置为5

Perl 提供 . 操作符,它做字串连接处理。比如: $almost = "Fred" . "Flitstone"; # 返回 FredFlitstone?

$a = (1,3); 把 3 赋予 $a。

引用,$ref_to_var = \$var; 不过 Perl 的引用要远比 C 的指针更安全

当用于匹配操作时,有时候 =~ 和 !~ 分别读做“匹配”和“不匹配”(因为“包含”和“不包含”会让人觉得有点模糊)。

里描述的 =~ 和 !~ 操作符把它们左边的标量表达式和在右边的三个引起类操作符之一绑定在一起: m// 用于匹配一个模式,
s/// 用于将某个符合模式的子字串代换为某个字串,而 tr/// (或者其同义词,y///)用于将一套字符转换成另一套
(如果把斜杠用做分隔符,你可以把 m// 写成 //,不用写 m。)如果 =~ 或 !~ 的右手边不是上面三个,
它仍然当作是 m// 匹配操作,不过此时你已经没有地方放跟在后面的修饰词了(参阅后面的“模式修饰词”),并且你必须操作自己的引号包围:
 print "matches"   if   $somestring =~ $somepattern;
 
 
 
 
 
 每次成功匹配了一个模式(包括替换中的模式),操作符都会把变量 $`,$&,和 $' 分别设置为匹配内容左边内容,
 匹配的内容和匹配内容的右边的文本。这个功能对于把字串分解为组件很有用:

"hot cross buns" =~ /cross/;
print "Matched: <$`> $& <$'>\n";    # Matched: <hot > cross < buns>
print "Left:    <$`>\n";            # Left:    <hot >
print "Match:   <$&>\n";            # Match:   <cross>
print "Right:   <$'>\n";            # Right:   < buns>

 

如果没有绑定操作符,隐含地用 $_ 做“标题”:
   /new life/ and            # 搜索 $_ 和 (如果找到)
   /new civilizations/      # 再次更宽范围地搜索 $_

   s/sugar/aspartame/         # 把一个替换物替换到 $_ 里

   tr/ATCG/TAGC            # 修改在 $_ 里表示的DNA

 

为了有更好的颗粒度和提高效率,你可以用圆括弧捕捉你特别想分离出来的部分。每对圆括弧捕捉与圆括弧内的模式相匹配的子模式。
圆括弧由左圆括弧的位置从左到右依次排序;对应那些子模式的子字串在匹配之后可以通过顺序的变量 $1,$2,$3 等等获得:

   $_ = "Bilbo Baggins's birthday is September 22";
   /(.*)'s birthday is (.*)/;
   print "Person: $1\n";
   print "Date: $2\n";
$`, $&, $' 和排序的变量都是全局变量,它们隐含地局部化为属于此闭合的动态范围。它们的存在直到下一次成功的匹配或者当前范围的结尾,
以先到者为准。我们稍后在其它课题里有关于这方面内容里更多介绍。

 

m// 操作符搜索标量 EXPR 里面的字串,查找 PATTERN。如果使用 / 或 ? 做分隔符,那么开头的 m 是可选的。? 和 ' 做分隔符时都有特殊含义:
前者表示只匹配一次;后者禁止进行变量代换和六种转换逃逸(\U 等,后面描述)。

 

你可以用方括弧创建一个创建一个指向匿名数组的引用:
$arrayref = [1, 2, ['a', 'b', 'c', 'd']];
在这里我们组合成了一个三个元素的匿名数组,该数组最后一个元素是一个指向有着四个元素的匿名数组(在图8-2里演示)。
(我们稍后描述的多维语法可以用于访问这些东西。比如, $arrayref->[2][1] 将具有数值“b”。)

你可以用花括弧创建一个指向匿名散列的引用:
$hashref = {
        'Adam' => 'Eve',
        'Clyde' => $bonnie,
        'Antony' => 'Cleo' . 'patra',
};

对象构造器:
构造器可以用下列任何方法调用:
$objref = Doggie::->new(Tail => 'short', Ears => 'long');  #1
$objref = new Doggie:: Tail => 'short', Ears => 'long';       #2
$objref = Doggie->new(Tail => 'short', Ears => 'long');    #3
$objref = new Doggie Tail => 'short', Ears => 'long';         #4

 

$$foo 是指 $foo 指向的标量值,@$bar 是 $bar 指向的数组值, %$glarch 是 $glarch 指向的散列数值,等等
   $foo       = "three humps";
   $scalarref   = \$foo;      # $scalarref 现在是一个指向 $foo 的引用
   $camel_model    = $$scalarref;   # $camel_model 现在是"three humps"

 

创建和访问一个两维数组
下面是如何把一个两维数组放在一起的方法:
   # 给一个数组赋予一个数组引用列表。
   @Aoa = (
      ["fred", "barney" ],
      ["george", "jane", "elroy" ],
      ["homer", "marge", "bart" ],
   );
print $AoA[2][1];      # 打印 "marge"
整个列表都封装在圆括弧里,而不是花括弧里,因为你是在给一个列表赋值而不是给引用赋值。如果你想要一个指向数组的引用,那么你要使用方括弧:
# 创建一个指向一个数组的数组的引用。
$ref_to_AoA = [
[ "fred", "barney", "pebbles", "bamm bamm", "dino", ],
[ "homer", "bart", "marge", "maggie", ],
[ "george", "jane", "elroy", "judy", ],
];

print $ref_to_AoA->[2][3];      # 打印 "judy"
请记住在每一对相邻的花括弧或方括弧之间有一个隐含的 ->。因此下面两行:
   $AoA[2][3]
   $ref_to_AoA->[2][3]

等效于下面两行:
   $AoA[2]->[3]
   $ref_to_AoA->[2][3]
不过,在第一对方括弧前面没有隐含的 ->,这也是为什么 $ref_to_AoA 的解引用要求开头的 ->。还有就是要记住你可以用负数索引从一个数组后面向前面计数,因此:

   $AoA[0][-2]
是第一行的倒数第二个元素。

 

常被遗忘的建议
实习 Perl 程序员应该注意下面的事项:
记住许多操作符在列表环境里和在标量环境里的行为是不同的。比如:

      ($x) = (4,5,6);      # 列表环境;$x 设置为 4
      $x = (4,5,6);      # 标量环境;$x 设置为 6

      @a = (4,5,6);
      $x = @a;      # 标量环境;$x 设置为 3(数组列表)
     
 @a={"hepoo","wo","jj"};
$len=@a ;数组的个数 $len=3;

    
如果你需要 =~ 的时候不要使用 =;这两个构造区别相当大:
$x = /foo/;      # 在 $_ 中搜索“foo”,把结果放在 $x
$x =~ /foo/;      # 在 $x 中搜索“foo”,抛弃结果

@user1=(); #把@user1清空 
$x=$#int1; #$#这个变量返回数组最后个数的值(index)$x=4

 

ARGV 必须大写。$ARGV[0] 是 C 的 argv[1],而 C 的 argv[0] 是 $0。

在 Perl 里,变量以 $,@,或者 % 开头。

程序参数可以通过 @ARGV,而不是 $1,$2,等等获得的。

 

4、 显示消息、退出常见的简单写法
  die ‘Error on program’;
  也可以在条件不满足的情况下使用
  die ‘Configuration error’ unless($doc->getDocumentElement

 

Perl的引用类似C的指针,所谓的引用事实上就是地址。取一个变量的地址用反斜杠”\”操作符,例如 $p=\$x; 那么$p就是一个指向$x变量的指针。
要引用指针的值,使用”$”操作符,例如 print $$p; 就是打印$x的值。
引用不单单可以引用变量,也可以引用数组、HASH表、函数,取函数的地址可以使用*操作符。

 

$b=$int1[0]; #$b等于数组的第一个元素值$b=1 
$c=@int1[0]; #$c同上$c=1,因些呼叫数组中值有两种方法

$int1[0,1]=[7,8]; #将7赋给数组的第一个元素将8赋给数组第二个元素.

 

 

keys(%array)操作符可生成由关联数组%array中的所有当前关键字组成的列表。即返回奇数个元素(第1,3,5,7...个)的列表。 
values(%array)操作符返回由关联数组%array中所有当前值组成的列表,即返回偶数个列表。 
echo(%array)操作符返回由一个关键字和一个值对构成的两个元素的表。对同一数组再操作时返回下一对值直至结束。
若没有更多的对时,echo()返回空表。 (这在打印全部列表中很有用) 

 

删除一对在关联数组中的数据:delete $ARRAY{key};delete 是 Perl 所提供的函数,作用是删除关联数组中的一个key以及这个 key 所对应的 value。
使用方法是 在 delete 函数之后,指定关联数组中要删除的key名称。 
关联数组的综合举例: 

%fred=(one,"zmd",two,"cxm"); $a=$fred{one};--- #$a等于"zmd" 
$b=$fred{two}---#$b等于"cxm" 
$fred{two}="yes"--- #%fred=(one,"zmd",two,"yes") 
@number=keys(%fred)--- #@list=(one,two
@user=values(%fred)---#@user=("zmd","cxm") 
($number,$name)=echo(%fred)--- #此时$number的值为one,$name的值为"zmd",再执行一次$number为值为two,$name的值为"cxm") 

@a=%fred--- #将关联数组fred指定给数组a,这时@a=(one,"zmd",two,"cxm") 
%b=@a---#将数组a指定给关联数组b,这时%b=(one,"zmd",two,"cxm") 
delete $fred{one}---#将关联数组中key值为one的一对key-value删除,这时%fred=(two,"cxm") 
%name=()---#把%name关联数组置空 

 

 

惯用C的程序员要注意,在PERL中,字符串的末尾并不含有隐含的NULL字符,NULL字符可以出现在串的任何位置。

交换元素:以用子数组形式来交换元素:
    @array[1,2] = @array[2,1];

 

(3)chop--数组去尾
    chop的意义是去掉STDIN(键盘)输入字符串时最后一个字符--换行符。而如果它作用到数组上,则将数组中每一个元素都做如此处理。
    @list = ("rabbit", "12345","quartz");
    chop (@list); # @list = ("rabbi", "1234","quart") now

 

二、读文件
  语句$line = <MYFILE>;从文件中读取一行数据存储到简单变量$line中并把文件指针向后移动一行。<STDIN>为标准输入文件,通常为键盘输入,不需要打开。
  语句@array = <MYFILE>;把文件的全部内容读入数组@array,文件的每一行(含回车符)为@array的一个元素。
三、写文件
  形式为:
    open(OUTFILE, ">outfile");
    print OUTFILE ("Here is an output line.\n");

四、判断文件状态
1、文件测试操作符
  语法为:-op expr,如:
    if (-e "/path/file1") {
    print STDERR ("File file1 exists.\n");
    }

五、命令行参数
  象C一样,PERL也有存储命令行参数的数组@ARGV,可以用来分别处理各个命令行参数;与C不同的是,$ARGV[0]是第一个参数,而不是程序名本身。
    $var = $ARGV[0]; # 第一个参数
    $numargs = @ARGV; # 参数的个数
  PERL中,<>操作符实际上是对数组@ARGV的隐含的引用,其工作原理为:
1、当PERL解释器第一次看到<>时,打开以$ARGV[0]为文件名的文件;
2、执行动作shift(@ARGV); 即把数组@ARGV的元素向前移动一个,其元素数量即减少了一个。
3、<>操作符读取在第一步打开的文件中的所有行。
4、读完后,解释器回到第一步重复。
  例:
    @ARGV = ("myfile1", "myfile2"); #实际上由命令行参数赋值
    while ($line = <>) {
    print ($line);
    }
  将把文件myfile1和myfile2的内容打印出来。
六、打开管道
  用程序的形式也可以象命令行一样打开和使用管道(ex:ls > tempfile)。如语句open (MYPIPE, "| cat >hello"); 打开一个管道,发送到MYPIPE的输出成为命令"cat >hello"的输入。由于cat命令将显示输入文件的内容,故该语句等价于open(MYPIPE, ">hello"); 用管道发送邮件如下:
    open (MESSAGE, "| mail dave");
    print MESSAGE ("Hi, Dave! Your Perl program sent this!\n");
    close (MESSAGE);

,/$def/只匹配以def结尾的字符串
\B在单词内部匹配:/\Bdef/匹配abcdef等,但不匹配def;/def\B/匹配defghi等;/\Bdef\B/匹配cdefg、abcdefghi等,但不匹配def,defghi,abcdef。

字符"."匹配除换行外的所有字符,通常与*合用

字符"|"指定两个或多个选择来匹配模式。如:/def|ghi/匹配def或ghi。

匹配操作符 =~、!~
   =~检验匹配是否成功:$result = $var =~ /abc/;若在该字符串中找到了该模式,则返回非零值,即true,不匹配则返回0,即false。!~则相反。

语法为s/pattern/replacement/,其效果为将字符串中与pattern匹配的部分换成replacement。如:
     $string = "abc123def";
     $string =~ s/123/456/; # now $string = "abc456def";
   在替换部分可使用模式次序变量$n,如s/(\d+)/[$1]/,但在替换部分不支持模式的特殊字符,如{},*,+等,如s/abc/[def]/将把abc替换为[def]。

 

肯定的和否定的预见匹配
   肯定的预见匹配语法为/pattern(?=string)/,其意义为匹配后面为string的模式,相反的,(?!string)意义为匹配后面非string的模式,如:
     $string = "25abc8";
     $string =~ /abc(?=[0-9])/;
     $matched = $&; # $&为已匹配的模式,此处为abc,而不是abc8

抱歉!评论已关闭.