PHP正则表达式
1.什么是正则表达式
正则表达式(Regular Expression,regexp)是一种描述字符串结构的语法规则,是一个特定的格式化模式,用于验证各种字符串是否匹配(Match)这个特征,进而实现高级的文本查找、替换、截取内容等操作。例如,若想要使Apache服务器解析PHP文件,需要在Apache的配置文件中添加能够匹配出以“.php”结尾的配置“.php”就是一个简单的正则表达式。
正则表达式在发展过程中出现了多种形式,一种是POSIX规范兼容的正则表达式,包括基本语法BRE(Base Regular Expression)和扩展语法ERE(Extended Regular Expression)两种规则,用于确保操作系统之间的可移植性,但最终没有成为标准只能作为一个参考。另一种是当Perl(一种功能丰富的编程语言)发展起来后,衍生出来了PCRE(Perl Compatible Regular Expressions,Perl兼容正则表达式)库,使得许多开发人员可以将PCRE整合到自己的语言中,PHP中也为PCRE库的使用提供了相应的函数。
如何使用正则表达式
在PHP的开发中,经常需要根据正则匹配模式完成对指定字符串的搜索和匹配。此时,可使用PHP提供的PCRE相关内置函数。preg_match()函数是最常用的一个函数,下面介绍此函数的几种常见用法。
1.执行匹配
preg_match()函数的第1个参数是正则表达式,第2个参数是被搜索的字符串,示例如下。
$result = preg_match('/web/','phpwebphpweb');var_dump($result); //输出:int(1)
在上述示例中,“/web/”中的“/”是正则表达式的定界符。当函数匹配成功时返回1,匹配失败时返回0,如果发生错误则返回false。由于被搜索字符串中包含“web”,因此函数的返回值为1。
值得一提的是,PHP中的PCRE正则函数都需要在正则表达式的前后加上定界符“/”,并且定界符可以自己设置,只要保持前后一致即可。
2.获取匹配结果
preg_match()函数的第3个参数用于以数组形式保存匹配到的结果,示例如下。
preg_match('/web/','phpwebphpweb',$matches);print_r($matches); //输出:Array ( [0] => web )
需要注意的是,preg_match()函数在正则匹配时,只要匹配到符合的内容,就会停止继续匹配。因此,虽然示例中字符串有两个“bad”,但在匹配结果中只有一个。
3.设置偏移量
preg_match('/web/','phpwebphpweb',$matches,PREG_OFFSET_CAPTURE);print_r($matches); //输出:Array ( [0] => Array ( [0] => web [1] => 3 ) )
示例中preg_match()的第4个参数设置为“PREG_OFFSET_CAPTURE”,表示将第一次匹配到指定规则的内容所在位置的偏移量添加到$matches中,待查字符串的开始位置从0开始计算。例如,字符串“abdbc”中的“a”的偏移量是0,“c”的偏移量是4。
通过打印结果可以看出,preg_match()根据正则的规则在字符串“preg_match(‘/web/‘,’phpwebphpweb’,$matches,PREG_OFFSET_CAPTURE);”中匹配到了指定的字符串“web”,且“web”字符的位置偏移量为3。
2.正则表达式快速入门
1.正则表达式的组成
在PHP的PCRE函数中,一个完整的正则表达式是由4部分内容组成的,分别为定界符、元字符、文本字符和模式修饰符。其中,元字符是具有特殊含义的字符,如“^”“.”或“*”等,文本字符就是普通的文本,如字母和数字等。模式修饰符用于指定正则表达式以何种方式进行匹配,如i表示忽略大小写,x表示忽略空白字符等,具体示例如下所示。
preg_match('/.*it/','ITHeima'); // 匹配结果:0preg_match('/.*it/i','ITHeima'); //匹配结果:1
在上述示例中,“._”用于匹配任意字符,因此正则表达式“/._it/”可以匹配任意含有“it”的字符串,如“it”“itheima”等。当添加模式修饰符“i”时,表示可匹配的内容忽略大小写,如所有含“IT”“It”“iT”和“it”的字符串都可以。需要注意的是,在编写正则表达式时,元字符和文本字符在定界符内,模式修饰符一般标记在结尾定界符之外。
正则表达式定义了许多元字符用于实现复杂匹配,而若要匹配的内容是这些字符本身时,就需要在前面加上转义字符“\”,如“^”和“\”等,具体示例如下。
preg_match('/\^/','123^456',$matches);print_r($matches); //输出结果:Array ( [0] => ^ )preg_match('/\*/','123*456',$matches);print_r($matches); //输出结果:Array ( [0] => * )preg_match('/\\\/','123\456',$matches);print_r($matches); //输出结果:Array ( [0] => \ )
在上述示例中,由于PHP的字符串存在转义问题,因此在代码中书写的“\”实际只保存了一个“\”。从输出结果可以看出,利用正则表达式的转义字符“\”成功匹配出了特殊字符。
2.获取所有匹配结果
在PHP中,preg_match_all()函数的功能与preg_match()函数类似,区别在于preg_match()函数在第一次匹配成功后就停止查找,而preg_match_all()函数会一直匹配到最后才停止,获取到所有相匹配的结果。下面介绍preg_match_all()函数的几种常用的使用方法。
1.执行匹配
利用preg_match_all()执行正则表达式匹配,示例代码如下。
$result = preg_match_all('/web/','phpwebphpweb');var_dump($result); //输出: int(2)
从上述示例可知,preg_match_all()函数的第1个参数表示正则表达式,第2个参数是被搜索的字符串。该函数执行成功时返回匹配的次数,如果返回0表示没有匹配到;当发生错误时返回false。
2.获取匹配结果
preg_match_all()函数的第3个参数可以保存所有匹配到的结果,具体示例如下。
preg_match_all('/web/','phpwebphpweb',$matches);print_r($matches); //输出:Array ( [0] => Array ( [0] => web [1] => web ) )
值得一提的是,preg_match_all()函数还有第4个参数,用于设置匹配结果在第3个参数中保存的形式,默认值为PREG_PATTERN_ORDER,表示在结果数组的第1个元素$matches[0]中保存所有匹配到的结果;如果将值设置为PREG_SET_ORDER,表示结果数组的第1个元素保存第1次匹配到的所有结果,第2个元素保存第2次匹配到的所有结果,以此类推。
3.正则表达式语法
1.定位符与选择符
1.定位符
在程序开发中,经常需要确定字符在字符串中的具体位置。例如,匹配字符串的头部或尾部。利用正则表达式元字符中的定位符可以实现字符定位,具体示例如下。
<?php$subject = "It's a nice day today";//匹配字符串开始的位置preg_match('/^It/', $subject,$matches);print_r($matches); //输出结果:Array ( [0] => It )//匹配字符串开始的位置preg_match('/today$/', $subject,$matches);print_r($matches); //输出结果:Array ( [0] => today )?>
从上述示例可以看出,正则表达式中定位符“^”可用于匹配字符串开始的位置,定位符“$”用于匹配字符串结尾的位置。
2.选择符
若要查找的条件有多个,只要其中一个满足即可成立时,可以用选择符“|”。该字符可以理解为“或”,具体使用示例如下。
<?php$subject = "123456";preg_match_all('/34|56|78/', $subject,$matches);print_r($matches); //输出结果:Array ( [0] => Array ( [0] => 34 [1] => 56 ) )?>
从以上示例可以看出,只要待匹配字符串中含有选择符“|”设置的内容就会被匹配出来。
2.字符范围与反斜线
1.字符范围
在正则表达式中,对于匹配某个范围内的字符,可以用中括号“[]”和连字符“-”来实现。且在中括号中还可以用反义字符“^”,表示匹配不在指定字符范围内的字符。下面以使用preg_match_all()函数匹配“AbCd”为例,具体的用法如下表所示。
| 示例 | 说明 | 匹配结果 |
|---|---|---|
| [abc] | 匹配字符a、b、c | b |
| [^abc] | 匹配字符a、b、c以外的字母 | A、C、d |
| [B-Z] | 匹配字母B-Z范围内的字符 | C |
| [^a-z] | 匹配字母a-z范围内的字符 | A、C |
| [a-zA-Z0-9] | 匹配大写字母、小写字母和数组0-9范围内的字符 | A、b、C、d |
需要注意的是,字符“-”在通常情况下只表示一个普通字符,只有在表示字符范围时才作为元字符来使用。“-”连字符表示的范围遵循字符编码的顺序,如“a-Z”“z-a”“a-9”都是不合法的范围。
2.反斜线
在正则表达式中,“\”除了前面讲解的可作转义字符外,还具有其他功能。例如,匹配不可打印的字符、指定预定义字符集等。反斜线的常用功能如下表所示。

从表中可以看出,利用预定的字符集可以很容易完成某些正则匹配。例如,大写字母、小写字母和数字可以使用“\w”直接表示,若要匹配0到9之间的数字可以使用“\d”表示,有效的使用反斜线的这些功能可以使正则表达式更加简洁,便于阅读。
3.字符的限定与分组
1.点字符和限定符
点字符“。”用于匹配一个任意字符,限定符(?、+、*、{})用于匹配某个字符连续出现的次数。关于点字符和限定符的详细说明如下表所示。

2.贪婪与懒惰匹配
当点字符和限定符连用时,可以实现匹配指定数量范围的任意字符。例如,“^pre.*end$”可以匹配以pre开始到end结束,中间包含零个或多个任意字符的字符串。正则表达式在实现指定数量范围的任意字符匹配时,支持贪婪匹配和惰性匹配两种方式。
所谓贪婪表示匹配尽可能多的字符,而惰性表示匹配尽可能少的字符。在默认情况下是贪婪匹配,若想要实现惰性匹配,需在上一个限定符的后面加上“?”符号。具体示例如下所示。
<?php//贪婪匹配$subject = "phphphph";preg_match('/p.*h/', $subject,$matches);print_r($matches); //输出结果:Array ( [0] => phphphph )//懒惰匹配preg_match('/p.*?h/', $subject,$matches);print_r($matches); //输出结果:Array ( [0] => ph )?>
从上述示例可以看出,贪婪匹配时,会获取最先出现的p到最后出现的h,即可获得匹配结果为“phphphph”;懒惰匹配时,会获取最先出现的p到最先的出现的h,即可获取匹配结果“ph”。
3.括号字符
在正则表达式中,括号字符“()”有两个作用:一是改变限定符的作用范围;二是分组。接下来,针对这两个作用分别进行讲解。
1.改变限定符的作用范围
改变作用范围前:
正则表达式:firm|sh可匹配的结果:firm、sh
改变作用范围后:
正则表达式:fi(rm|sh)可匹配的结果:firm、fish
从上述示例可知,小括号实现了匹配firm和fish,而如果不使用小括号,则变成了firm和sh。
2.分组
分组前:
正则表达式:bana{2}可匹配的结果:banaa
分组后:
正则表达式:ba(na){2}可匹配的结果:banana
在上述示例中,未分组时,表示匹配2个a字符;而分组后,表示匹配2个“na”字符串。
4.模式修饰符
在PHP正则表达式的定界符外,还可以使用模式修饰符,用于进一步对正则表达式进行设置。其中,常用的模式修饰符如下表所示。

若要忽略匹配字符的大小写,除了使用选择符“|”和中括号“[]”外,还可以直接在定界符外添加i模式符;若要忽略目标字符串中的换行符,可以使用模式修饰符s等。除此之外,模式修饰符还可以根据实际需求多个组合在一起使用。例如,既要忽视大小写又要忽视换行,则可以使用直接使用is。在编写多个模式修饰符时没有顺序要求。
4.正则表达式运算符优先级
PHP中常用的正则表达式运算符优先级由高到低的顺序如下表所示。

