Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1631155
  • 博文数量: 1481
  • 博客积分: 26784
  • 博客等级: 上将
  • 技术积分: 17045
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-12 09:22
文章分类

全部博文(1481)

文章存档

2014年(10)

2013年(353)

2012年(700)

2011年(418)

分类: 系统运维

2012-05-07 11:14:47

前言:终于上网了,还是在网吧里,在这里把我总结的正则表达式的一些用法与大家分享一下,由于我不方便上网,因此可能不能及时回复,望大家见谅

说明:
细说正则表达式上篇
本文为任鹏原创,每一个例子都是任鹏亲自设计并且通过调试的。本文主要讲解正则表达式的一些特殊用法,并不涉及正则的基础知识,基础知识部分请参考《细说php》一书和老师的课件
由于篇幅关系本文分为上下篇,上篇主要讲解后向引用,模式修正符,以及贪婪模式和非贪婪模式,下篇主要讲解特殊字符的转义,欢迎大家挑错^_^

1.后向引用
()的作用,可以将括号中的值存储起来,一般结合preg_match函数或者preg_replace函数使用

通过调用preg_match($pattern,$string,$match) 然后$match[n]当中保存着正则第n个()中匹配的字符串
通过调用preg_replace函数可以进行后向引用 \\n 或 $n

例1:
$string = 'say#hello#world';
$pattern = '/#(\w+)#/';

echo preg_replace($pattern,'@\\1@',$string); //后向引用的时候一定要加两个反斜杠\\n n为数字1-99,表示引用正则表达式中第n个()中匹配的字符串
结果: say@hello@world

例2:
$string = 'say#hello#world';
$pattern = '/#(\w+)#/';

echo preg_replace($pattern,'@$1@',$string); //也可以使用$n n为1-99,表示引用正则表达式中第n个()中匹配的字符串
结果: say@hello@world

例3:
$string = 'say#hello#world';
$pattern = '/#(\w+)#/';

echo preg_replace($pattern,'2${1}2',$string);

结果: say2hello2world

//这里用${1}来引用正则表达式中第一个()中匹配的内容,而不是$12 ,这样会混淆是取出第12个()匹配的内容还是第一个()匹配的内容后跟上字符2

如果想使用()但是不想保存()中的值可以使用(?:)

例4:
$string = '@hello@#world#';
$pattern = '/@(\w+)@#(\w+)#/';

echo preg_replace($pattern,'%${1}%&${1}&',$string); //这里${1}匹配的是正则中第一个()中匹配的字符串 hello
结果: %hello%&hello&

例5:
$string = '@hello@#world#';
$pattern = '/@(?:\w+)@#(\w+)#/';

echo preg_replace($pattern,'%${1}%&${1}&',$string); //由于正则中第一个()加上了?:,所以这里${1}匹配的是第二个()中匹配的字符串 world
结果: %world%&world&


2.模式修正符
i 不区分大小写(这个没什么说的)
x 不区分正则表达式的空白 '/a b/x' 相当于'/ab/' 因此可以匹配字符串 'ab'
s 如果不加s,.只匹配非\n的任何字符,加上s之后,.也匹配\n
m 重点说一下,如果不加m,^只匹配整个字符串开始,$只匹配整个字符串的结尾以及结尾之前的\n
e 结合preg_replace时候使用,查看老师上课的例子,这里不介绍了
U 翻转贪婪或非贪婪模式(详细使用方法见 3.贪婪模式与非贪婪模式)
A 与^效果一样 '/abc/A' 相当于 '/^abc/'
D $不匹配字符串结尾前的\n

例1:
$string = "abc\n";
$pattern = '/abc$/'; //不加m和D的时候,$匹配字符串的结尾以及结尾之前的\n,注意必须是字符串结尾前面的\n,其他的\n不可以
echo preg_match($pattern,$string,$match);
结果:输出 1

例2:
$string = "abc\nfff";
$pattern = '/abc$/'; //不加m和D的时候,$匹配字符串的结尾以及结尾之前的\n,注意必须是字符串结尾前面的\n,其他的\n不可以
echo preg_match($pattern,$string,$match);
结果:输出 0

例3:
$string = "abc\n";
$pattern = '/abc$/D'; //不加m,加上D,$就只能匹配字符串结尾,不能匹配结尾前的\n
echo preg_match($pattern,$string,$match);
结果:输出 0

下面详细介绍m和s的几种情况

m 如果不加m,^只匹配整个字符串开始,$只匹配整个字符串的结尾以及结尾前的\n

例4:
$string = '#a#';
$pattern = '/^#\w#$/';

echo preg_match($pattern,$string,$match);

结果:输出 1

例5:
$string = "#a#\n@@@"; //注意,这里的字符串必须用双引号,因为我在字符串中用了\n表示换行符,单引号不解析转义字符,\n会原样输出
$pattern = '/^#\w#$/';

echo preg_match($pattern,$string,$match);

结果:输出 0

例6:
$string = "@@@\n#a#"; //注意,这里的字符串必须用双引号,因为我在字符串中用了\n表示换行符,单引号不解析转义字符,\n会原样输出
$pattern = '/^#\w#$/';

echo preg_match($pattern,$string,$match);

结果:输出 0

但是如果加上m,^匹配整个字符串的开头或者是任何\n(换行符)之后,$匹配整个字符串的结尾或者是任何\n(换行符)之前

例7:
$string = "@@@\n#a#\n@@@";
$pattern = '/^#\w#$/m';

echo preg_match($pattern,$string,$match);

结果:输出 1

注意,加上m之后,$匹配的是整个字符串的结尾或者是\n(换行符 next line)之前,但是不匹配\r(回车符)之前,见下例

例8:
$string = '#a#
@@@'; //注意,window操作系统你按一下回车键相当于输出 \r\n两个字符,所以#a#后面按一下回车相当于#a#\r\n,由于$不匹配\r,所以该正则不匹配该字符串
$pattern = '/^#\w#$/m';

echo preg_match($pattern,$string,$match);

结果:输出 0

例9:
$string = '@@@
#a#'; //注意,$string相当于 @@@\r\n#a# 加上m之后,^匹配\n之后,所以该正则匹配该字符串
$pattern = '/^#\w#$/m';

echo preg_match($pattern,$string,$match);

结果:输出 1


模式修正符号s,如果不加s,.只匹配非\n的任何字符,加上s之后,.也匹配\n

例10:
$string = "#\n#"; //用双引号
$pattern = '/#.#/';

echo preg_match($pattern,$string,$match);

结果:输出 0

例11:
$string = "#\n#"; //用双引号
$pattern = '/#.#/s';

echo preg_match($pattern,$string,$match);

结果:输出 1

例12:
$string = "#
#"; //在windows系统中,按一下回车相当于\r\n,所以.不能匹配两个字符
$pattern = '/#.#/s';

echo preg_match($pattern,$string,$match);

结果:输出 0

例13:
$string = "#
#";
$pattern = '/#..#/s'; //两个点 . . 分别匹配 \r和\n

echo preg_match($pattern,$string,$match);

结果:输出 1


3.贪婪模式与非贪婪模式

在perl模式的正则表达式中, * + ?{} 都是贪婪模式

例1:
$string = 'abababa';
$pattern = '/a\w+a/';

if(preg_match($pattern,$string,$match)){
echo "匹配字符串 ".htmlentities($match[0]);
}else{
echo "不匹配";
}

结果:会输出 匹配字符串 abababa

详解:
'/a[a-z]+a/' 这个正则的意思是 字母a 一个或多个小写字母 字母a, 我们看一下原串 $string = 'abababa'; 这里面貌似可以匹配该正则的子字符串有 aba ababa abababa ,到底要匹配哪一个呢?

匹配的过程是这样的:php的正则引擎首先会在字符串'abababa'中从左向右顺序查找有没有与正则表达式 /a[a-z]+a/ 匹配的字符串,当php引擎读到了前三个字符aba时,它发现已经匹配了该正则表达式,但是由于+是贪婪模式,所以它会继续向右读取字符串,看看还能不能继续匹配,当php引擎读到了前五个字符ababa时,它发现又能匹配正则了,但是它还不满足,还是贪婪地继续向后查找还能不能继续匹配,直到读完 abababa后,它发现后面没有字符了,因此会停止继续查找,返回匹配的字符串 abababa。

那么假如 $string = 'ababababc'; 这个过程和上面的大致相同,但是当php引擎读到 abababa后,发现字符串还没有结束,于是它贪婪地继续向后搜索,它读到abababab时发现不匹配,那么继续读,读到ababababc时,发现不匹配,那么继续读,但是后面没字符了,它发现自己贪婪过头了,于是开始回溯,去掉最后一个字符c 变为abababab,发现不匹配,继续回溯,去掉最后一个字符b,变为abababa,满足了正则,于是返回这个值


但是我们有时候不需要贪婪模式,尤其是匹配大段html标签的时候

例2:
$string = '

nav area
content area
footer area
';
$pattern = '/
.*<\/div>/';

if(preg_match($pattern,$string,$match)){
echo "匹配字符串 ".htmlentities($match[0]);
}else{
echo "不匹配";
}

结果:匹配字符串
nav area
content area
footer area


详解:
'/
.*<\/div>/' 这个正则的意思是
中间可以有0个或多个字符
,(这里面.*可以匹配任意字符,包括
这样的标签)
我们看一下字符串变量 $string = '
nav area
content area
footer area
';
$string 里面貌似可以满足该正则表达式意思子字符串可以是
nav area
nav area
content area
nav area
content area
footer area
但是由于.*是贪婪的,所以只会匹配到最长的

假如我们只想匹配
nav area
或者
content area
这样单独的
标签对,而不是所有的
nav area
content area
footer area

那么我们需要取消贪婪模式,让正则尽可能少地匹配,见例3

例3:
$string = '
nav area
content area
footer area
';
$pattern = '/
.+?<\/div>/'; //注意这里在+号后面加了一个? 这样就表示+号会尽可能少地匹配,因此匹配到第一个
结束标签时便返回匹配结果,而不是贪婪地向下继续查找

if(preg_match($pattern,$string,$match)){
echo "匹配字符串 ".htmlentities($match[0]);
}else{
echo "不匹配";
}

结果:匹配字符串
nav area


下面我们说一下模式修正符号U,U并不完全是取消贪婪模式的意思,U真正意思是翻转贪婪与非贪婪模式,见如下例子

例4:
$string = 'abababa';
$pattern = '/a\w+a/U';

if(preg_match($pattern,$string,$match)){
echo "匹配字符串 ".htmlentities($match[0]);
}else{
echo "不匹配";
}

结果:匹配字符串 aba

详解:本来 /a\w+a/ 是贪婪模式的,那么后面加上U就变为非贪婪模式了

例5:
$string = 'abababa';
$pattern = '/a\w+?a/U';

if(preg_match($pattern,$string,$match)){
echo "匹配字符串 ".htmlentities($match[0]);
}else{
echo "不匹配";
}

结果:匹配字符串 abababa

详解:本来 /a\w+?a/ 是非贪婪模式的,因为 +? 加号后面有个问号,所以非贪婪,但是加上模式修正负U之后,就变为贪婪模式了

所以说,模式修正符U 并不是取消贪婪模式的意思,而是翻转贪婪模式,当未加上U的正则是贪婪模式的时候,加上U之后就变为非贪婪,当未加上U的正则是非贪婪模式的时候,加上U之后就变为贪婪


/**********************************************************************************************************************************************************************

细说正则表达式上篇结束

**********************************************************************************************************************************************************************/

原文地址:

阅读(509) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~