首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

4.8  正则表达式

Regular Expressions

如果你需要比前面提供的方法更加复杂的查找功能,可以使用正则表达式。正则表达式是一个描述模式(pattern)的字符串。正则表达式函数会将模式和另一个字符串进行比较,检

查字符串是否和模式匹配。一些函数会告诉你是否匹配,另一些则改变字符串。

PHP支持两种不同类型的正则表达式:POSIX 和Perl兼容 (Perl-compatible)的。POSIX正则表达式比Perl兼容的功能弱,并且有时速度慢,但是易于阅读。正则表达式有3种作用:匹配,用于从字符串提取信息;用新文本取代匹配的文本;把字符串拆分成小块的数组。PHP为Perl和POSIX正则表达式中的这3种行为都提供了函数。例如,ereg( )进行POSIX匹配, 而 preg_match( )进行 Perl匹配。幸运的是,基本的POSIX和 Perl正则表达式之间有一些相似之处,所以我们在深入研究每个库的细节之前可以先介绍它们。

4.8.1  基础

The Basics

正则表达式中大部分字符都是直接量字符,这意味着它们只匹配自身。例如,如果在字符串"Dave was a cowhand"中查找正则表达式"cow",由于"cow"出现在字符串中,所以将得到匹配的结果。

一些字符在正则表达式中有特殊含义。例如,在正则表达式开头的^符号表示它必须匹配字符串的开头(或者更准确地说,是把正则表达式定位在字符串开头):

ereg('^cow', 'Dave was a cowhand');     //返回flase

ereg('^cow', 'cowabunga!');             //返回true

类似地,一个在正则表达式末尾出现的美元符号($)表示它必须匹配字符串的末尾(也就是说,把正则表达式定位在字符串的末尾):

ereg('cow$', 'Dave was a cowhand');     //返回false

ereg('cow$', "Don't have a cow");       //返回true

在正则表达式中的句点(.)匹配任意单个字符:

ereg('c.t', 'cat');                     // returns true返回true

ereg('c.t', 'cut');                     // returns true返回true

ereg('c.t', 'c t');                     // returns true返回true

ereg('c.t', 'bat');                     // returns false返回false

ereg('c.t', 'ct');                      // returns false返回false

如果想要匹配特殊字符中的某一个(称为元字符,metacharacter),需要使用反斜杠对它进行转义:

ereg('\$5\.00', 'Your bill is $5.00 exactly');     // returns true 返回true

ereg('$5.00', 'Your bill is $5.00 exactly');       // returns false返回false

正则表达式默认区分大小写,所以正则表达式"cow"和字符串"COW"是不匹配的。如果想要执行一个不区分大小写的POSIX风格的匹配,可以使用eregi( )函数。要使用Perl

风格的正则表达式,则可以使用preg_match( ),但是需要指定一个标志来说明是不区分大小写的匹配(在本章稍后讨论Perl风格正则表达式的细节时会介绍)。

到目前为止,我们还没有做任何用字符串函数(比如strstr( ))无法处理的事,那为什么需要正则表达式呢?正则表达式的真正强大来自于它们可以指定抽象模式来匹配许多不同的字符序列。在正则表达式中可以指定3种基本的抽象模式:

l          在字符串中可以出现的字符集(例如,字母、数字和特殊的标点符号)

l          可选择性的集合(例如,"com""edu""net""org")

l          在字符串中重复的序列(例如,至少一个但是不多于5个的数字字符)

这3种模式可以按无数种方法结合在一起来创建正则表达式,以匹配像有效电话号码和URL之类的内容。

4.8.2  字符类

Character Classes

要在模式中指定可接受的字符集,可以建立一个自己的字符类或使用预定义的字符类。可以通过用中括号包含可接受字符来建立自己的字符类:

ereg('c[aeiou]t', 'I cut my hand');     // returns true 返回true

ereg('c[aeiou]t', 'This crusty cat');   // returns true 返回true

ereg('c[aeiou]t', 'What cart?');        // returns false 返回false

ereg('c[aeiou]t', '14ct gold');         // returns false 返回false

正则表达式引擎发现一个"c",然后检查下一个字符是否是"a"、"e"、"i"、"o" 或"u"中的一个。如果它不是一个元音,则匹配失败并且引擎返回去查找另一个"c"。如果找到一个元音,引擎检查下一个字符是否是"t"。如果是的话,引擎达到匹配的末尾并返回true。如果下一个字符不是"t",则引擎返回去查找另一个"c"

可以在字符类开头使用^来否定该类:

ereg('c[^aeiou]t', 'I cut my hand');    // returns false返回false

ereg('c[^aeiou]t', 'Reboot chthon');    // returns true返回true

ereg('c[^aeiou]t', '14ct gold');        // returns false返回false

在这里,正则表达式引擎查找一个"c",然后是一个非元音字符,接着是一个"t"

可以用连字符(-)定义一个字符范围。简单的字符类如“所有字母”和“所有数字”:

ereg('[0-9]%', 'we are 25% complete');            //返回true

ereg('[0123456789]%', 'we are 25% complete');     //返回true

ereg('[a-z]t', '11th');                           //返回false

ereg('[a-z]t', 'cat');                            //返回trueereg('[a-z]t', 'PIT');                            //返回false

ereg('[a-zA-Z]!', '11!');                         //返回false

ereg('[a-zA-Z]!', 'stop!');                       //返回true

当你指定一个字符类时,一些特殊字符就失去了它们的意义,同时其他字符有了新的意义。特别的是,当^字符不再是锚(anchor,就像之前讨论过的,用于指定以某个字符开头)而是用于否定字符类(当它是左括号的第一个字符时)时,美元符$和句点.也在字符类中失去了它们原来的意义($原指以某字符结尾;.原可代替任意字符),而仅仅是一个字符。例如,[^\]]匹配任一不是右括号的字符,[$.^]匹配任一美元符号、句点或^。

不同的正则表达式库为字符类定义了不同的缩写,包括数字、字母表的字符和空白符。POSIX风格和Perl风格正则表达式在缩写语法上是有区别的。例如,POSIX用"[[:space:]]"表示空白类,而Perl则是"\s"

4.8.3  选择性

Alternatives

可以使用竖线(|)字符在正则表达式中指定可供选择的部分:

ereg('cat|dog', 'the cat rubbed my legs');        //返回true

ereg('cat|dog', 'the dog rubbed my legs');        //返回true

ereg('cat|dog', 'the rabbit rubbed my legs');     //返回false

选择的优先级会让人惊讶:'^cat|dog$'选自'^cat''dog$',意味着它匹配以"cat"开头或"dog"结尾的一行。如果想要一行只包括"cat" 或 "dog",需要使用正则表达式'^(cat|dog)$'

可以组合字符类和选择符号,例如,为字符串作不以大写字母开头的检查:

ereg('^([a-z]|[0-9])', 'The quick brown fox');  //返回false

ereg('^([a-z]|[0-9])', 'jumped over');          //返回true

ereg('^([a-z]|[0-9])', '10 lazy dogs');  //返回true

4.8.4  重复序列

Repeating Sequences

要指定一个重复模式,要使用量词(quantifier)。量词在重复模式后面,用来说明要重复这个模式多少次。表4-6显示了POSIX 和 Perl正则表达式都支持的量词

表4-6:正则表达式量词

量  词

意  义

?

0或1

*

0或更多

+

1或更多

                                        

续表4-6:正则表达式量词

量  词

意  义

{n}

n次

{n,m}

至少n次,不超过m次

{n,}

至少n次

要重复单个字符,只要简单地把量词放在字符后面:

ereg('ca+t', 'caaaaaaat');                        //返回true

ereg('ca+t', 'ct');                                //返回false

ereg('ca?t', 'caaaaaaat');                        //返回false

ereg('ca*t', 'ct');                                //返回true

使用量词和字符类,我们可以实际地做一些有用的事情,例如匹配有效的美国电话号码:

ereg('[0-9]{3}-[0-9]{3}-[0-9]{4}', '303-555-1212');      //返回true

ereg('[0-9]{3}-[0-9]{3}-[0-9]{4}', '64-9-555-1234');     //返回false

4.8.5  子模式

Subpatterns

可以使用小括号把几个正则表达式组合在一起作为一个单独的单元来对待,这个单元被称为子模式(subpattern):

ereg('a (very )+big dog', 'it was a very very big dog');  //返回true

ereg('^(cat|dog)$', 'cat');                                     //返回true

ereg('^(cat|dog)$', 'dog');                                     //返回true

小括号也使得与子模式匹配的子串被捕获。如果把一个数组当作第三个参数传递给匹配函数,任何捕捉到的子串都将被放进该数组:

ereg('([0-9]+)', 'You have 42 magic beans', $captured);

//返回true并对$captured进行赋值

数组的第零个元素设置为匹配的整个字符串。第一个元素是与第一个子模式匹配的子串(如果有一个的话),第二个元素是与第二个子模式匹配的子串,依此类推。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论