文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档> PHP 中使用正则表达式

PHP 中使用正则表达式

时间:2007-12-28  来源:061107


正则表达式(Regular Expression)是用于描述字符排列模式的一种语法规则。它主要用于字符串的模式分割、匹配、查找及替换操作。正则表达式早期仅用于Unix系统程序,现在已被绝大多数系统、程序所支持。随着正则表达式移植到交叉平台的程序语言的发展,其功能也日益完善。本章将讲述正则表达式的基本知识以及在PHP中的应用。
6.1  正则表达式简介
正则表达式的名称源于一系列数学领域的研究成果,其主要的模式匹配思想来自于SNOBOL语言。正则表达式具有一套完整语法体系,提供了一种灵活且直观的字符串处理方法。正则表达式通过构建具有特定规则的模式,与输入信息进行比较,实现字符串的匹配操作。
所谓模式是指具有某种共通特征的字符串表达式。例如,对电子邮件地址而言,其共通特性是一般必须包含字符“@”;一个标准的URL地址一般必须以“http://”或“https://”开头;搜索相同类型的文件使用类似于“*.php”格式的字符串——这些都是“模式”。
在程序语言中,通常将模式表达式(即正则表达式)包含在两个反斜线“/”之间,如“/apple/”。用户只要把需要匹配的模式内容放入定界符之间即可。作为定界的字符也不仅仅局限于“/”。除了字母、数字和斜线(“\”)以外的任何字符都可以作为定界符,像“#”、“/”、“!”等都是可以的。
在PHP中有两套正则表达式函数库。一套是由PCRE(Perl Compatible Regular Expression)库提供的;另一套是由POSIX(Portable Operation System interface)扩展库提供的。前者使用以“preg_”为前缀命名的函数;后者使用以“ereg_”为前缀命名的函数。两者功能相似,只是执行效率略有差异。
使用正则表达式的原因之一,是在典型的搜索和替换操作中,只能对确切文字进行匹配,对于动态文本的搜索就有困难了,甚至是不可能的。下面是一个检测数字表示合法性的正则表达式。
/^-?\d+$|^-?0[xX][\da-fA-F]+$/
该正则表达式可以匹配所有二进制、八进制、十进制、十六进制的正负整数。另一个具体的例子是匹配电子邮件地址格式的正则表达式。
/^[0-9a-zA-Z_-]+@[0-9a-zA-Z_-]+(\.[0-9a-zA-Z_-]+){0,3}$/
对于初学者而言,这些可能比较费解。在学习完本章内容后,读者就可以真正理解上述表达式的具体含义了。


6.2  正则表达式的语法规则
正则表达式描述了一种字符串的排列模式,主要用于字符串的模式分割、匹配、查找及替换等操作。正则表达式是主要由原子(普通字符,如英文字符)、元字符(有特殊功用的字符)以及模式修正字符组成。一个正则表达式中至少包含一个原子。他们各自功能和含义有所不同,下面将分别讲述正则表达式的组成元素及其语法规则。
6.2.1  原子(Atom)
原子是组成正则表达式的基本单位。在分析正则表达式时,应作为一个整体。原子字符是由所有未显式指定为元字符的打印和非打印字符组成。这包括所有的英文字母、数字、标点符号以及其他一些符号。原子包括以下内容。

    单个字符、数字,如a~z,A~Z,0~9。

    模式单元,如(ABC)。可以理解为由多个原子组成的大的原子。

    原子表,如[ABC]。

    重新使用的模式单元。

    普通转义字符。

    转义元字符。
表6.1列出了正则表达式所使用的普通转义字符。
表6.1                                                              普通转义字符
原    子
说    明
\d
匹配一个数字;等价于 [0-9]
\D
匹配除数字以外任何一个字符;等价于 [^0-9]
\w
匹配一个英文字母、数字或下划线;等价于 [0-9a-zA-Z_]
\W
匹配除英文字母、数字和下划线以外任何一个字符;等价于 [^0-9a-zA-Z_]
\s
匹配一个空白字符;等价于 [ \f\n\r\t\v]
\S
匹配除空白字符以外任何一个字符;等价于 [^ \f\n\r\t\v]
\f
匹配一个换页符;等价于 \x0c 或 \cL
\n
匹配一个换行符;等价于 \x0a 或 \cJ
\r
匹配一个回车符;等价于 \x0d 或 \cM
\t
匹配一个制表符;等价于 \x09 或 \cI
\v
匹配一个垂直制表符;等价于 \x0b 或 \cK
\oNN
匹配一个八进制数字
\xNN
匹配一个十六进制数字
\cC
匹配一个控制字符
6.2.2  元字符(Meta-character)
元字符是用于构造规则表达式的具有特殊含义的字符。如果要在正则表达式中包含元字符本身,必须在其前加上“\”进行转义。表6.2列出了正则表达式中支持的元字符。
表6.2                                                                    元字符
元  字  符
说    明
*
0次、1次或多次匹配其前的原子
+
1次或多次匹配其前的原子
?
0次或1次匹配其前的原子
.
匹配任何一个字符
|
匹配两个或多个选择
^ 或 \A
匹配字符串串首的原子
$ 或 \Z
匹配字符串串尾的原子
\b
匹配单词的边界
\B
匹配除单词边界以外的部分
[]
匹配方括号中的任一原子
[^]
匹配除方括号中的原子外的任何字符
()
其整体表示一个原子
{m}
表示其前原子恰好出现m次
{m,n}
表示其前原子至少出现m次,至多出现n次(n>m)
{m,}
表示其前原子出现不少于m次
下面将这些元字符分为几类分别讲解。
1.原子表
原子表“[]”中存放一组原子,彼此地位平等,且仅匹配其中的一个原子。如果想匹配一个“a”或“e”使用/ae/,例如:/Pr[ae]y/ 匹配“Pray”或者“Prey”。原子表“[^]”或者称为排除原子表,匹配除表内原子外的任意一个字符。例如:/p[^u]/ 匹配“part”中的“pa”,但无法匹配“computer”中的“pu”,因为“u”在匹配中被排除。
通常,在原子表中用“-”连接一组按ASCII码顺序排列的原子,用以简化书写。如/x[0123456789]/可以写成/x[0-9]/,用来匹配一个由“x”字母与一个数字组成的字符串;/0[xX][0-9a-fA-F]/匹配一个简单的十六进制数字,如“0x9”。/[^0-9a-zA-Z_]/ 匹配除英文字母、数字和下划线以外任何一个字符,其等价于/\W/。
2.重复匹配
正则表达式中有一些用于重复匹配其前原子的元字符:“?”、“*”、“+”。他们主要的不同是重复匹配的次数不同。

    元字符“?”表示0次或1次匹配紧接在其前的原子。例如:/colou?r/匹配“colour”或“color”。

    元字符“*”表示0次、1次或多次匹配紧接在其前的原子。例如://可以匹配“”、“”或“”等HTML标签,并且不严格地控制大小写。

    元字符“+”表示1次或多次匹配紧接在其前的原子。例如:/go+gle/匹配“gogle”、“google”或“gooogle”等中间含有多个“o”的字符串。上文中提及的十六进制数字的例子,实际上更加完善的匹配表达式是/0?[xX][0-9a-fA-F]+/,可以匹配“0x9B3C”或者“X800”等。读者可以自行进行分析。
要准确地指定原子重复的次数,还可以使用元字符“{}”指定所匹配的原子出现的次数。“{m}”表示其前原子恰好出现m次;“{m, n}”表示其前原子至少出现m次,至多出现n次;“{m, }”表示其前原子出现不少于m次。以下是一些示例。

    /zo{1,3}m/只能匹配字符串“zom”、“zoom”或“zoom”。

    /zo{3}m/只能匹配字符串“zooom”。

    /zo{3, }m/      可以匹配以“z”开头,“m”结束,中间为至少3个“o”的字符串。

    /bo{0,1}u/可以匹配字符串“bought a butter”中的“bou”和“bu”,其完全等价于 /bo?u/。
3.边界限制
在某些情况下,需要对匹配范围进行限定,以获得更准确的匹配结果。元字符“^”(或“\A”)置于字符串的开始,确保模式匹配出现在字符串首端;“$”(或“\Z”)置于字符串的结束,确保模式匹配出现在字符串尾端。
例如,在字符串“Tom and Jerry chased each other in the house until Tom’s uncle come in”中使用/^Tom/或^ATom/匹配句首的“Tom”;而/in$/或/in\Z/匹配句末“come in”中的“in”。如果不加边界限制元字符,将获得更多的匹配结果。
在使用各种编辑软件的查找功能时,可以通过选择“按单词查找”获得更准确的结果。正则表达式中也提供类似的功能。元字符“\b”对单词的边界进行匹配;“\B”对单词的内部进行匹配。
例如:在字符串“This island is a beautiful land”中使用/\bis\b/可以匹配单词“is”,而与“This”或者“island”无关。/\bis/与单词左边界匹配,可以匹配单词“is”和“island”中的“is”;/\Bis/不与单词左边界匹配,可以匹配单词“is”和“This”中的“is”。/\Bis\B/ 将明确的指示不与单词的左、右边界匹配,只匹配单词的内部。所以在这个例子中没有匹配结果。
4.元字符“.”
元字符“.”匹配除换行符外任何一个字符,相当于[^\n](Unix系统)或[^\r\n](Windows系统)。例如:/pr.y/可以匹配目字符串“prey”、“pray”或“pr%y”等。
通常,可以使用“. *”组合来匹配除换行符外的任何字符串。在一些书籍中也称其为“全匹配符”或“单含匹配符”。例如:/a.*z/ 表示可以匹配以字母“a”开头,字母“z”结束的任意不包括换行符的字符串。“. +”也可以完成类似的匹配功能,所不同的是其至少匹配一个字符。例如:/a.+z/将不匹配字符串“az”。
5.模式选择符
元字符“|”又称模式选择符。在正则表达式中匹配两个或更多的选择之一。例如:在字符串“There are many apples and pears.”中,/apple|pear/在第一次运行时匹配“apple”;再次运行时匹配“pear”。也可以继续增加选项,如/apple|pear|banana|lemon/。
6.模式单元
元字符“()”将其中的正则表达式变为原子(或称模式单元)使用。与数学表达式中的括号类似,“()”可以作为一个单元被单独使用。
例如:/(Dog)+/匹配的“Dog”、“DogDog”、“DogDogDog”……,因为紧接着“+”前的原子是用元字符“()”括起来的字符串“Dog”。
一个模式单元中的表达式将被优先匹配或运算。系统自动将这些模式单元的匹配结果依次存储起来,在需要时可以用“\1”、“\2”、“\3”的形式进行引用。当正则表达式包含有相同的模式单元时,这种方式非常便于对其进行管理。
例如:/^\d{2}([\W])\d{2}\1\d{4}$/匹配“12-31-2006”、“09/27/1996”、“86 01 4321”等字符串。但上述正则表达式不匹配“12/34-5678”的格式。这是因为模式“[\W]”的匹配结果“/”已经被存储。下个位置“\1”引用时,其匹配模式也是字符“/”。
当不需要存储匹配结果时使用非存储模式单元“(?:)”。例如:/(?:a|b|c)(D|E|F)\1g/ 将匹配“aEEg”。在一些正则表达式中,使用非存储模式单元是必要的。否则,需要改变其后引用的顺序。上例还可以写成 /(a|b|c)(C|E|F)\2g/。
7.模式匹配的顺序
在使用正则表达式时,需要注意匹配的顺序。通常,正则表达式按照由左至右的顺序依次匹配。表6.3列出了其他字符的匹配顺序。
表6.3                                                            模式匹配的顺序
顺    序
元  字  符
说    明
1
()
模式单元
2
? * + {}
重复匹配
3
^ $ \b \B \A \Z
边界限制
4
|
模式选择
6.2.3  模式修正符(Pattern Modifiers)
模式修正符扩展了正则表达式在字符匹配、替换操作时的某些功能。这些扩展或者说修正增强了正则表达式的处理能力。模式修正符一般标记于整个模式之外,并且可以组合使用,如“/apple/i”、“/cat|dog/Uis”等。表6.4列出了一些常用的模式修正符及其功能说明。
表6.4                                                            模式匹配的顺序
模式修正符
说    明
i
可同时匹配大小写字母
m
将字符串视为多行
s
将字符串视为单行,换行符作为普通字符看待
x
模式中的空白忽略不计
S
当一个模式将被使用若干次时,为加速匹配起见值得先对其进行分析
续表
模式修正符
说    明
U
匹配到最近的字符串
e
将替换的字符串作为表达式使用
下面是几个简单的示例,用以说明模式修正符的使用,在后面的章节中还会继续讨论。

    /apple/i匹配“apple”或“Apple”等,忽略大小写。

    /I love you/ix匹配“iLoveYou”,忽略大小写以及空白。

    //U 将依次匹配字符串“Cool musicFew years ago…”中的“”、“”和“”。而//却匹配到最后一个可用的字符串,即“Cool music”。

    //Uis 将HTML文件视为单行字符穿,忽略大小写和换行符。匹配其中中的所有以“h”开头的标签,如“”、“”等。

6.3  PHP中的正则表达式函数
在PHP中有两套正则表达式函数库。一套是由PCRE(Perl Compatible Regular Expression)库提供的。PCRE库使用和Perl相同的语法规则实现了正则表达式的模式匹配,其使用以“preg_”为前缀命名的函数。另一套是由POSIX(Portable Operation System interface)扩展库提供的。POSIX扩展的正则表达式由POSIX 1003.2定义,一般使用以“ereg_”为前缀命名的函数。
两套函数库的功能相似,执行效率稍有不同。一般而言,实现相同的功能,使用PCRE库的效率略占优势。下面详细介绍其使用方法。
6.3.1  正则表达式的匹配
1.preg_match()
函数原型:int preg_match (string $pattern, string $content [, array $matches])
preg_match ()函数在$content字符串中搜索与$pattern给出的正则表达式相匹配的内容。如果提供了$matches,则将匹配结果放入其中。$matches[0]将包含与整个模式匹配的文本,$matches[1]将包含第一个捕获的与括号中的模式单元所匹配的内容,以此类推。该函数只作一次匹配,最终返回0或1的匹配结果数。代码6.1给出preg_match()函数的一段代码示例。
代码6.1  日期时间的匹配
     //需要匹配的字符串。date函数返回当前时间
     $content = "Current date and time is ".date("Y-m-d h:i a").", we are learning PHP together.";
     //使用通常的方法匹配时间
     if (preg_match ("/\d{4}-\d{2}-\d{2} \d{2}:\d{2} [ap]m/", $content, $m))
     {
        echo "匹配的时间是:" .$m[0]. "\n";
     }
     //由于时间的模式明显,也可以简单的匹配
     if (preg_match ("/([\d-]{10}) ([\d:]{5} [ap]m)/", $content, $m))
     {
         echo "当前日期是:" .$m[1]. "\n";
         echo "当前时间是:" .$m[2]. "\n";
     }
?>
这是一个简单动态文本串匹配实例。假设当前系统时间是“2006年8月17日13点25分”,将输出如下的内容。
匹配的时间是:2006-08-17 01:25 pm
当前日期是:2006-08-17
当前时间是:01:25 pm
2.ereg()和eregi()
ereg()是POSIX扩展库中正则表达式的匹配函数。eregi()是ereg()函数的忽略大小写的版本。二者与preg_match的功能类似,但函数返回的是一个布尔值,表明匹配成功与否。需要说明的是,POSIX扩展库函数的第一个参数接受的是正则表达式字符串,即不需要使用分界符。例如,代码6.2是一个关于文件名安全检验的方法。
代码6.2  文件名的安全检验
     $username = $_SERVER['REMOTE_USER'];
     $filename = $_GET['file'];
     //对文件名进行过滤,以保证系统安全</P%3

相关阅读 更多 +
排行榜 更多 +
楼梯球3d

楼梯球3d

休闲益智 下载
艾特足球最新版

艾特足球最新版

休闲益智 下载
贪食蛇战机手机版

贪食蛇战机手机版

休闲益智 下载