用户名: 密   码:
   飞诺网 加入收藏
飞诺网 网站开发 VBScript ASP Asp.net Jsp php XML CGI-Perl 搜索引擎 ajax web技术
CGI-Perl系列教程 CGI-Perl技术文档 CGI-Perl实例

您当前的位置:飞诺网 >>  网站开发 >>  CGI-Perl >> CGI-Perl实例

Perl正则表达式讲解,真的非常详细

www.diybl.com    时间 : 2008-09-12  作者:佚名   编辑:辉辉 点击:   [ 评论 ]

语法 | 意味着匹配unsigned char或者char且把已 匹配的字符串保存在反向引用中。替换可以是很微妙的,因为对于替换行为有一件重要的事情要记住:

·替换总是试图匹配阂括号中的第一个项目;如果匹配不成功,才尝试第二个样式的匹配,依次类推。

这就是所谓的极左匹配,它能解释人们接触正则表达式时所遇到的许多错误。拿前面的例子来说,假定改变了圆括号中条目的次序,那么该例子变为:

$declaration = ‘ unsigned char string [80]’;

$declaration = ~ m " (char | unsigned char )";

这能匹配字符串unsigned char (就像在unsigned char string [80] 中那样)吗?不能,它匹配char(即, unsigned char string [80])。因为在列表中char处在第一位,所以比字符串unsigned char要有限。正则表达式匹配char,因而在反向引用中保存了错误的替换。这种错误信息很普通,所以这里指出一点:

·总是拿优先级最高的字符串先去匹配,最符殊的字符串先去匹配。如果读者不这么做,则会陷入痛苦的等待中,例如:

    $line = ~ m " (. * | word )";

绝不会匹配word。这是因为word是.*(也就是四个任一字符)的一个实例。同时正则表达式极左匹配,所以首先拾取.*,因而:

$line = " wordstar";

$line = ~ m " (.* | word)";

将匹配wordstar(即,整个字符串而不是word。.*匹配任何字符集,且因.*在替换中处于第一位,所以始终比"word"优先。因而没有匹配wordstar中的word:

     $line = ~ m "(word | .*)"; #since ‘ word’ is first.

在不知道某单词是否为定界符或者该单词是否为复数的情况下,替换是很有帮助的。例如,如下代码:

$line = ‘ words’;

$line = ‘ word’;

$line = ~m "word (s|$)" sg; # word may be followed by the character ‘!’ or ‘$’.

两者都能匹配。该语法将匹配字符串word,无论word后跟字符串结束标记或者s。用下式替换$:

    $line = ~ m " word (s | \b)";

这就得到处理复数的好方法。

 

9.3.8 原则8

Perl用(?..)语法给正则表达式提供扩展名。

在Perl历史上的某一天(大约Perl 4向Perl5转变时),为了使正则表达式集合增长,人们决定Perl必须"达到元字符标准"。一些人争论道有太多的元字符存在,而另一些人不同意,直到键盘上没有太多的元字符为止。

到那是人们在认为形成一种独特的可用于多次扩展的构造是一个好主意。查看键盘后,发现一个相当普通的字符(?)在任何地方都不用。因此,它被定了下来。语法看起来像这样:

    (? <special character(s)> <text>)

这里,<special character(s)>代表扩展名,<text>是表达式使用的文本。四个最常用的扩展名在表9-5中给出。

 

  此外,有一个运算符(?#comment)允许用户把注嵌入正则表达式。不过因为x修饰符的出现(后面讨论)这个运算符已过时了。在其它方面,扩展名像其它正则表达式结构一样工作。把它们放到正则表达式中。如果输入:

    $line = ~ m " I love(?! oranges)" ;

则由于(?!禁止oranges跟着字符串I love,所以此行代码匹配love figs 而不是I love oranges。然而,这个表达式匹配的是I love orange或者I love ripe oranges,原因是它仅禁止以字符串oranges开头的字符串。可以输入:

    $line = ~ m " I love (?!. * orange )";

来禁止这些字符串。

事实上,修饰符(?!是Perl语有中最容易理解的结构。人们希望它处理如下事情:

    $line = ~ m "(?! Oranges ) I love ";

使之不匹配oranges I love。这明显地不会成功。结构(?l)仅当下一个子串不是oranges时才匹配。 因而,在这个例子中,使匹配无效的唯一位置是在字符串的开头 在其他任何位置都不会做任何工作。正则表达式向前执行,并已发现紧接着的六个字符不是"oranges"。因而要求满足,执行下一个要求。

另两个用得最多的表达式是(?:…)和(?=…) 。例如:(?:…)通过除去不必要的反向引用而使正则表达式更高效。如果输入:

    $line = ~ m " (?:int | unsigned int | char )\s*(\w+)";

以得到变量名,而可能不希望保存变量的类型,因而用(?:)。表达式匹配给定类型,后跟空格,后跟变量名(\w+)。但是把变量名保存在$1中而不是$2中,(?:)被忽略。这样可节省时间和内存,尤其是在大型模式匹配中。

另一个表达成(?:)仅在使用g修饰符时有用,下面我们将仔细介绍。g修饰符可让读者在正则表达式中从读者停止的位置后面开始,不必从头再来。例如,如果有看起来像下面这样的数据:

    BLOCK1 <data> BLOCK2 <data2> BLOCK3 <data3>

而读者想首先匹配<data>,其次匹配<data2>,第三(最后)匹配<data3>,于是可输入:

    $line = ~ m " BLOCK \d(,*?) (BLOCK\d | $)" g;

第一次运行会匹配<data>,但是在第二个BLOCK之后,就把"匹配指针"放到了错误位置。如果输入为:

    $line = ~ m "BLOCK \d (.*?) (?=BLOCK\d)"g;

则由于说明"匹配BLOCKl和BLOCK2之间的最少数量的文本"所以匹配相同数量的文本。为了下一次匹配的目的而忽略了BLOCK2,以致于使下一次调用正则表达式能匹配<data2>。图9-8概括了二者之间的区别。用(?=)形式可以现在输入如下语句:

用(?=)形式可以现在输入如下语句:

BLOCK 1 <data> BLOCK2 <data2> BLOCK3 <data3>

while ($line = ~ m "BLOCK\d(.*?) (?=BLOCK\d | $ )"g)

{

        print " $1 \n";

}

1 2 3 4 5 6 7 8 9 10 11 12
如果图片或页面不能正常显示请点击这里
CGI-Perl实例推荐文章

文章评论