`
webcode
  • 浏览: 5951680 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

细说正则表达式上篇

 
阅读更多

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

说明:
细说正则表达式上篇
本文为任鹏原创,每一个例子都是任鹏亲自设计并且通过调试的。本文主要讲解正则表达式的一些特殊用法,并不涉及正则的基础知识,基础知识部分请参考《细说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 = '<div>nav area</div><div>content area</div><div>footer area</div>';
$pattern = '/<div>.*<\/div>/';

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

结果:匹配字符串 <div>nav area</div><div>content area</div><div>footer area</div>

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

假如我们只想匹配<div>nav area</div>或者<div>content area</div>这样单独的<div></div>标签对,而不是所有的<div>nav area</div><div>content area</div><div>footer area</div>
那么我们需要取消贪婪模式,让正则尽可能少地匹配,见例3

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

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

结果:匹配字符串 <div>nav area</div>

下面我们说一下模式修正符号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之后就变为贪婪


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

细说正则表达式上篇结束

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

分享到:
评论

相关推荐

    正则表达式30分钟入门教程

    当然,如果你看完了这篇教程之后,发现自己明白了很多,却又几乎什么都记不得,那也是很正常的——我认为,没接触过正则表达式的人在看完这篇教程后,能把提到过的语法记住80%以上的可能性为零。这里只是让你明白...

    editplus 代码编辑器html c++ jsp css

    实际上这也是正则表达式的使用特例,“[0-9]”表示匹配0~9之间的任何特例,同样“[a-z]”就表示匹配a~z之间的任何特例 【1】正则表达式应用——替换指定内容到行尾 原始文本如下面两行 abc aaaaa 123 abc 444 ...

    EditPlus 2整理信箱的工具

    实际上这也是正则表达式的使用特例,“[0-9]”表示匹配0~9之间的任何特例,同样“[a-z]”就表示匹配a~z之间的任何特例 上面重复使用了“[0-9]”,表示连续出现的三个数字 “\0”代表第一个“[0-9]”对应的原型,...

    Editplus 3[1].0

    实际上这也是正则表达式的使用特例,“[0-9]”表示匹配0~9之间的任何特例,同样“[a-z]”就表示匹配a~z之间的任何特例 上面重复使用了“[0-9]”,表示连续出现的三个数字 “\0”代表第一个“[0-9]”对应的原型,...

    细说PHP、精要版、高清、高洛峰、pdf

    细说PHP精要版,一本不错的PHP入门书,前两天想要复习一下正则表达式,想起来这本书上说的还是比较清楚易懂的,就来csdn找,找了一个老版的模糊的要死。这本精简版的是高清的,刚好也有我要的内容。分享给大家。

    PHP中文网线上培训班-PHP编程.zip

    目录网盘文件永久链接 ...第6章 mysql数据库管理 第7章 mysql数据库管理1 第8章 mysql数据库管理2 第9章 会话控制 第10章 会话控制1 第11章 细说函数 ...第22章 php正则表达式 第23章 请求第三方api接口

    细说Linux细说Linux

    细说Linux 细说Linux 细说Linux 细说Linux 细说Linux 细说Linux

    C#_细说多线程(上下)

    C#_细说多线程(上下)

    《细说PHP》

    对于PHP应用开发的新手而言,《细说PHP》不失为一本好的入门教材,内容既实用又全面,辅以视频教程,使读者轻松掌握所学知识

    细说linux pdf

    细说linux pdf 兄弟连(lampbrother)李明linux课程pdf

    Nginx服务器初期基本配置指南

    pcre,有关正则表达式匹配;zlib,用于压缩。这些就不细说了,如果要安装最简版的nginx,记得准备好这两样东西就好了。 用root账户启动服务是比较危险的! 前段时间,测试服务器被黑掉了,终归到底是通过一个root...

    图表细说电子元器件(全部) 图表细说电子元器件(全部)

    图表细说电子元器件 图表细说电子元器件(全部)图表细说电子元器件(全部)

    细说PHP光盘源码,《细说PHP》配套源码,php资源下载,php代码

    细说PHP光盘源码,《细说PHP》配套源码,php资源下载,php代码

    细说PHP(精要版)part3

    《细说PHP(精要版)》简介:  PHP是开发Web应用系统最理想的工具,拥有易于使用、功能强大、成本低廉、安全性高、开发速度快且执行灵活等优点。《细说PHP(第2版)》自出版以来,销售一路在同类书籍中领先,已成为...

    细说PHP(第二版)

    细说PHP php 2012.10 第二版, 细说PHP php 2012.10 第二版,001

    高洛峰php细说php4

    《细说PHP》开发Web应用程序PHP是最理想的工具,易于使用、功能强大、成本低廉、高安全性、开发速度快且执行灵活。 《细说PHP》以实用为目标设计,包含PHP开发最主流的各项技术,对每一个知识点都进行了深入详细的...

    PHP课件 细说PHP345

    PHP课件 细说PHP

    《细说php 精要版》.(高洛峰) (高清 完整版)

    《细说php(第2版)》自出版以来,销售一路在同类书籍中领先,已成为php学习者首选的工具书。为了可以让读者携带方便及更精准地掌握php的重点、要点,同时能使之作为大学计算机系php教材普及,特别推出《细说php精要版...

    图表细说电子工程师识图速成手册.pdf

    图表细说电子工程师识图,从三极管、反馈电路、电源电路、振荡电路等方面综合图文并茂地介绍,特别适合初涉电子设计的开发人员。

Global site tag (gtag.js) - Google Analytics