PHP高级特性一之正则表达式用法

8/31/2015来源:PHP技巧人气:1535

php高级特性一之正则表达式用法

在PHP中,我们进行字符串处理时,能用字符串处理函数时我们当然要使用简单的字符串处理函数,但字符串处理函数的能力是有限的,所以我们就需要利用一个更强大的工具,那就是正则表达式。

简述正则表达式正则表达式是什么?

正则表达式就是描述字符串排列模式的一种自定义语法规则。正则表达式就是通过构建具有特定规则的模式,和输入字符串信息进行比较,然后进行分割、匹配、查找、替换等等的相关操作。正则表达式不是PHP中独有的,多种语言均可以使用正则表达式,在这里我们介绍正则在PHP中的用法。

使用场合

1. PHP中,如果可以用字符串处理函数完成的任务,我们就不要使用正则表达式。

2. 有一些复杂的操作,例如格式检验等等,只能用正则表达式完成。

3. 正则表达式也是一个字符串,但是它是具有特殊意义的字符串。

4. 它具有一些编写规则,也是一种模式,也可以把它看做一种编程语言。

5. 只有把正则表达式运用到某个函数中使用,才能发挥出正则表达式的作用,否则,它便是一个简单的字符串。

小例子

图片的匹配例子

1"/\<img\s*src=\".*?\"\/\>/iu"

这就是匹配HTML中的一个图片标签,例如可以匹配

1<img src="a.jpg"/>

PHP中的正则表达式函数库

在PHP中,有两套正则表达式函数库。

1.POSIX 扩展的正则表达式函数(ereg_)。

2.Perl 兼容的正则表达式函数(PReg_)。

Perl 兼容的函数库是后加的函数库,功能更加强大,另外javaScript 和 Perl 语言里面也会兼容这种模式,所以推荐学习 Perl 语言兼容的函数库。

在学习时,我们就需要学习下面两点

1. 正则表达式的语法

2. PHP中正则表达式的处理函数

正则表达式的语法

任何正则表达式都是由定界符号、原子、元字符、模式修正符号四部分来组成的。下面我们以上面的例子依次来介绍这四部分内容。

1"/\<img\s*src=\".*?\"\/\>/iu"

1. 定界符号

除了字母,数字和反斜杠 \ 以外的所有字符均可以为定界符。上面的例子中,开头和末尾的两个斜线 / 便作为定界符,我们还可以利用其它字符来定义,例如 | |,{ },# #等等,不过我们一般是使用斜线 / 作为定界符。

2. 原子

上面的例子中,img \s 均为原子。原子是正则表达式的最基本的组成单位,而且必须至少包含一个原子,正则表达式中可以单独使用的字符,就是原子。

使用时注意事项总结如下

1)原子包括所有打印字符和非打印字符,打印字符就是我们可以在屏幕上看到的字符例如abc等等,非打印字符就是我们看不到的字符,例如空格,回车等等。

2)\. \* \+ \? \< \( \< \>,所有有意义的字符,如果想作为原子使用,必须统统使用 \ 转义字符转义。

3)转义字符 \ 可以将有意义的字符转为有意义的字符,例如 * 是元字符,代表匹配一个字符零到多次,但是 \* 就代表了 * 这个字符。

4)另外转义字符还可以将没有意义的字符转成有意义的字符,例如 \d 可以表示任意一个十进制数字。总结如下:

\d:表示任意一个十进制的数字。

\D:表示任意一个除数字以外的字符。

\s:表示任意一个空白字符,如空格、回车、\t、\n

\S:表示任意一个非空白

\w:表示任意一个字,包括 a-z,A-Z,0-9,下划线_

\W:表示任意一个非字,\w 之外的任意一个字符

5)自定义原子表,定义一个中括号,表示匹配中括号中的任何一个内容,注意是任何一个。例如

正则表达式 “/[123]/” 和字符串 “abc2″可以匹配成功。

正则表达式 “/[a-z]/” 和字符串 “x3″可以匹配成功。

正则表达式 “/[1-3a-z]/” 和字符串 “x”可以匹配成功。

在这里[^]中括号里面写入^代表取反,表示除了原子表中的原子,但是^必须写在[]的第一个字符上。例如

[^a-z]代表除了a-z的所有字符

[^\n\t]代表除了换行和制表的所有字符

3. 元字符

上面的例子中,* ?均为元字符。元字符就是用来修饰原子的字符,不可以单独出现。

例如 * 代表匹配前面的原子零到多次,但如果想匹配 *,则必须要加转义号 \* 来表示

,特殊地,. 点也可以表示原子

元字符总结分类如下

1)* 表示其前面的原子可以出现 0 至多次

2)+ 表示前面的原子可以出现 1 至多次,即至少一个原子

3)? 表示前面的原子可以出现 0 次或 1 次

4){ } 用于自己定义前面原子出现的次数,另外分为以下几种

{m},m表示一个整数,则前面的数字必须出现m次

{m,n},m,n表示两个整数,m<n,表示前面出现的原子最少出现 m 次,最多出现 n 次。

{m,} m表示一个整数,表示最少出现 m 次,最多无限

所以 * 可以表示为 {0,},+ 可以表示为{1,},? 表示为 {0,1}

5). 默认情况下,表示除换行符外任意一个字符,和 * 组合表示可以匹配任意字符串,和 + 组合表示至少一个字符串

6)^ 直接在一个正则表达式的第一个字符出现,表示字符串必须以这个正则表达式开始,例如

^okay,表示字符串必须以 okay 开头

7)$ 直接在一个正则表达式的最后一个字符出现,则表示字符串必须以这个正则表达式结尾,例如

okay$,表示字符串必须以 okay 结尾。

注意:^okay$只是匹配一个okay字符,若要匹配 okay 开头okay结尾,则正则表达式可以写为 ^okay.*okay$

8)| 表示或的关系,它的优先级是最低的,最后考虑它的功能

9)\b 表示一个边界,例如

字符串 this is island,那么 \bis\b 则可以匹配,它匹配的是中间的 is,is两边是有边界的。

10)\B 表示一个非边界,例如

\Bis\b,则匹配第一个is,\bis\B则匹配第三个 is

11)() 括号,重点,作用总结如下

(1)将括号里面的元素作为一个大原子使用

即作为一个整体使用,例如 (abc)+,可以匹配abcabc….

(2)改变优先级

加上括号可以提高其优先级别。

(3)作为子模式使用

正则表达式中添加括号相当于添加了子模式。全部匹配作为一个大模式,放到数组的第一个元素中,每个()是一个子模式按顺序放到数组的其它元素中去。

在下面所说的 preg_match 方法中,结果会被赋值到 $arr 变量中,先匹配外层模式,再匹配内层模式。

12345$pattern="/(\d{4}(\W)\d{2}\W\d{2})\s+(\d{2}(\W)\d{2}\W\d{2})\s+(?:am|pm)/"; //正则表达式模式$string="today is 2010/09/15 15:35:28 pm..."; //需要和上面模式字符串进行匹配的变量字符串if(preg_match($pattern, $string, $arr)){print_r($arr);}

结果

12345678Array([0] => 2010/09/15 15:35:28 pm[1] => 2010/09/15[2] => /[3] => 15:35:28[4] => :)

(4)取消子模式

就将它作为大原子或者改变优先级使用。

只要在模式前面加一个 ?: 就可以取消子模式,例如

1(?:am|pm) //即不把(am|pm)作为一个子模式,直接将 am|pm 看做一个整体来使用。

(5)反向引用

可以在模式中直接将子模式取出来,再作为正则表达式模式的一部分, 如果是在正则表达式像替换函数preg_replace函数中, 可以将子模式取出, 在被替换的字符串中使用

\1 取第一个子模式、 \2取第二个子模式, …. \5 (注意是单引号还是双引号引起来的正则)

“\\1″ 在双引号引起来的正则,它是可以解释转义字符的,所以 \1 必须要写成 \\1‘\1′ 在单引号引起来的正则中,则不会出现这种情况,\1 仍然可以写成 \1

例如

1234567$pattern="/\d{4}(\W)\d{2}\\1\d{2}\s+\d{2}(\W)\d{2}\\2\d{2}\s+(?:am|pm)/"; //正则表达式模式$string="today is 2010/09/15 15:35:28 pm..."; //需要和上面模式字符串进行匹配的变量字符串if(preg_match($pattern, $string, $arr)){ echo "正则表达式 <b>{$pattern} </b>和字符串 <b>{$string}</b> 匹配成功<br>"; print_r($arr); echo '</pre>'; }

在上面的例子中,因为(\W)已经匹配了第一个斜杠/,它已经作为第一个子模式保存起来了,我们想继续使用这个匹配,我们就可以用 \\1 来表示,如果是单引号引起来的正则,则直接用 \1 来表示就可以了,后面的 \\2 和它是同样的原理。

4. 模式修正符号

上面的例子中,最后 / 后面的 i u 即为模式修正符号。

1)就是几个字母

2)可以一次使用一个,每一个都具有一定的意义,也可以连续使用多个符号

3)放在最后面,是对整个正则表达式调优用的,也可以说是对正则表达式功能的扩展。

归类如下:

i:表示在和模式进行匹配时不区分大小写

m:将每一行字符视为新的一行,也就是换行符后任何一行都可以当做一个整体字符串,主要的影响就在于 ^ 号和 $ 号。

例如:

12345$pattern = '/^abc/m'$string ='cde abcd efg'//可以匹配成功,因为加入m之后,第二行的abcd也当做一行了,也算是以abc开头

s:如果没有使用这个模式修正符号,那么 “.” 是不能当做换行符的,加入s,将字符串视为单行,那么 “.” 也就可以表示换行符了。

x:模式中的空白忽略不计,注意是模式中的。

123$pattern = '/a b c/x'$string ='abc'//可以匹配成功,因为加入x之后,a b c直接当做abc来看

e:正则表达式必须使用在 preg_replace函数中使用

A:必须以正则表达式开头,也就相当于前面加了 ^

Z:必须以正则表达式结尾,相当于后面加了 $

U:取消贪婪模式,或者 .*? 也可以取消贪婪模式,不过两个同时使用时会导致相反的结果,相当于负负得正的影响,同时出现则会又开启了贪婪模式 。

综上所述,正则表达式的组成为

/原子和元字符/模式修正符号,其中 / 为定界符号,不过有一些语言是不需要这个定界符的,例如 Python 等。

5.元字符的优先级(了解)

1)\ 转义符最高

2)(),(?:),{ },括号其次

3)* + ? {}

4)^ $ \b

5)|

6.常用的正则表达式

1)校验数字的表达式

1 数字:^[0-9]*$2 n位的数字:^\d{n}$3 至少n位的数字:^\d{n,}$4 m-n位的数字:^\d{m,n}$5 零和非零开头的数字:^(0|[1-9][0-9]*)$6 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$7 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$8 正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$9 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$10 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$11 非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$12 非零的负整数:^\-[1-9][]0-9″*$ 或 ^-[1-9]\d*$13 非负整数:^\d+$ 或 ^[1-9]\d*|0$14 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$15 非负浮点数:^\d+(\.\d+)?