正则表达式学习之回溯与固态分组/php
2017-09-22 20:31
453 查看
在笔记回溯和固态分组时,先介绍什么是反向引用
//反向引用
//示例
//回溯
//示例:(和注释(学习笔记__可能有错误的地方))
echo "\n";
$string3 = 'abbcbbcdef';
//固态分组:目的为了减少回溯次数
//示例:(有注释(学习笔记__可能有错误的地方))
//案例概述:比如要处理一批数据,原来格式为123.456,后来因为浮点数显示问题,部分数据格式变为123.456000000789这种,要求做到只保留小数点后面2-3位,但是,最后一位不能为0
echo '<p>';
$string4 = '123.456';
$patern1 = '/(\.\d\d[1-9]?)\d*/';
$patern2 = '/(\.\d\d[1-9]?)\d+/';
//patern1 和 patern2 ,相比之下,patern1如果处理的小数的小数位是3位的话,由于'*'匹配规则是一次或0次,会对字符在处理一次,而'+'则要求是1次或以上,所以对小数位为3位或者以上的话,能够简化匹配过程。
//然而简化匹配过程并不代表能够匹配到想要的结果,如果用$patern2 去匹配$string4的话,得到的结果将是123.45
//由于patern2至少要匹配长度为3的字符串,而'?'规则是匹配1或0次,那么当6匹配成功[1-9]后,'?'留下一个回溯点,
//'\d+'会继续匹配,由于‘6’以后没有字符了,所以放回到上一个回溯点,然后匹配'6'成功.所以捕获数组中'\\1'([1]的字符串)就是'.45';
//而没有实现我们想要的结果
//所以应用固化分组的特性,让'[1-9]?'一旦匹配成功就不能进行回溯了(因为'?'没有留下回溯点)
$patern3 = '/(\.\d\d(?>[1-9]?))\d+/';
$patern4 = '/(\.\d\d(?>[1-9]?))\d*/';
echo preg_match($patern3, $string4)? 1:0; //显然patern3匹配的结果是0(即是没有匹配到符合字符串)
echo '<p>';
echo preg_match($patern4, $string4)? 1:0; //而$patern4匹配的结果是1(说明匹配到了字符串);
echo '<p>';
//虽然patern3匹配失败但是也仅是限于3位或2位,而没有匹配成功也能达到保留3位或者两位的效果
//那么下面,我们将对第三位小数做讨论,当第三位小数位0时;
$string4 = '123.450';
echo preg_replace($patern3, '\\1', $string4);
echo '<p>';
echo preg_replace($patern4, '\\1', $string4);
echo '<p>';
echo preg_match($patern3, $string4, $matchs1);
echo '<p>';
echo preg_match($patern4, $string4, $matchs2);
echo '<p>';
var_dump($matchs1); //array(2) { [0]=> string(5) ".4501" [1]=> string(3) ".45" }
echo '<p>';
var_dump($matchs2); //array(2) { [0]=> string(5) ".4501" [1]=> string(3) ".45" }
//显然如果第三位小数为0,那么'\d+'就可以直接匹配'0',相比'\d*',省略一次匹配(因为是贪婪匹配,如果是懒惰匹配就不存在了);
//得出的结论就是,判断建议使用'\d*',替换建议使用'\d+';
//以上就是这一次学习的成果
//反向引用
//示例
$string = 'abcdebbcde'; $patern = '/([ab])\1/'; preg_match($patern, $string, $matchs); var_dump($matchs);
//分析://对于'([ab])',是匹配'ab'中的一个字符,而\1则是反向引用了捕获数组中匹配的第一个字符, //即是a或者b,而([ab])\1匹配的字符串则是 aa 或者 bb,但是在'abcdebbcde'中,第一个字符'a'满足要求, //即由([ab])匹配'a'成功,将捕获的内容保存在下标为1的捕获数组中,然后将匹配编号为1的字符的权利交给了'\1' //,所以这是([ab])\1匹配的内容为aa,但是由于第二个字符为'b',所以'aa'(\1)匹配失败,由于没有可供回溯的状态, //所以整个表达式在 $string 位置0处匹配失败,所以继续从 $string 位置1(即是字符串的第二个字符)处继续匹配,以此直至传动到 $string 位置5时, //([ab])\1成功匹配到 'bb',即是([ab])匹配的是b,而'\1'匹配的则是'b'.至此匹配结束.
//注意://在JavaScript中,由于浏览器解析引擎的不同,得到的结果也不一样,例如'\10' //而在Firefox、Opera等浏览器中,“\10”被解析成第10个捕获组的反向引用 //而在.NET中,如果正则表达式加了RegexOptions.ECMAScript参数,则这里的“\10”被解析成第1个捕获组的反向引用加一个普通字符“0”。 //实例: echo '<p>'; $string2 = 'abcc0aa0bb0'; $patern2 = '/([abc])\1(?:0)/'; $patern3 = '/([abc]\10)/'; preg_match($patern2, $string2, $matchs2); var_dump($matchs2); echo '<p>'; preg_match($patern3, $string2, $matchs3); var_dump($matchs3);
//回溯
//示例:(和注释(学习笔记__可能有错误的地方))
echo "\n";
$string3 = 'abbcbbcdef';
//每一次'.+',都会留下一个回溯点
$patern4 = '/a.+c/'; //贪婪匹配,尽可能匹配满足要求的字符串最长(即是字符串越短越好),(实现方法:倒序回溯匹配),所以回溯了3次 preg_match($patern4, $string3, $matchs4); var_dump($matchs4); echo '<p>'; $patern5 = '/a.+?c/'; //懒惰匹配,尽可能匹配满足要求的字符串最短(即是字符串越短越好)(实现方法:正序回溯匹配),所以回溯了2次 preg_match($patern5, $string3, $match 9a4e s5); var_dump($matchs5); //因此,回溯的效率和懒惰匹配和贪婪匹配没有关系,只是匹配的目标字符串长度不同
//固态分组:目的为了减少回溯次数
//示例:(有注释(学习笔记__可能有错误的地方))
//案例概述:比如要处理一批数据,原来格式为123.456,后来因为浮点数显示问题,部分数据格式变为123.456000000789这种,要求做到只保留小数点后面2-3位,但是,最后一位不能为0
echo '<p>';
$string4 = '123.456';
$patern1 = '/(\.\d\d[1-9]?)\d*/';
$patern2 = '/(\.\d\d[1-9]?)\d+/';
//patern1 和 patern2 ,相比之下,patern1如果处理的小数的小数位是3位的话,由于'*'匹配规则是一次或0次,会对字符在处理一次,而'+'则要求是1次或以上,所以对小数位为3位或者以上的话,能够简化匹配过程。
//然而简化匹配过程并不代表能够匹配到想要的结果,如果用$patern2 去匹配$string4的话,得到的结果将是123.45
//由于patern2至少要匹配长度为3的字符串,而'?'规则是匹配1或0次,那么当6匹配成功[1-9]后,'?'留下一个回溯点,
//'\d+'会继续匹配,由于‘6’以后没有字符了,所以放回到上一个回溯点,然后匹配'6'成功.所以捕获数组中'\\1'([1]的字符串)就是'.45';
//而没有实现我们想要的结果
//所以应用固化分组的特性,让'[1-9]?'一旦匹配成功就不能进行回溯了(因为'?'没有留下回溯点)
$patern3 = '/(\.\d\d(?>[1-9]?))\d+/';
$patern4 = '/(\.\d\d(?>[1-9]?))\d*/';
echo preg_match($patern3, $string4)? 1:0; //显然patern3匹配的结果是0(即是没有匹配到符合字符串)
echo '<p>';
echo preg_match($patern4, $string4)? 1:0; //而$patern4匹配的结果是1(说明匹配到了字符串);
echo '<p>';
//虽然patern3匹配失败但是也仅是限于3位或2位,而没有匹配成功也能达到保留3位或者两位的效果
//那么下面,我们将对第三位小数做讨论,当第三位小数位0时;
$string4 = '123.450';
echo preg_replace($patern3, '\\1', $string4);
echo '<p>';
echo preg_replace($patern4, '\\1', $string4);
echo '<p>';
echo preg_match($patern3, $string4, $matchs1);
echo '<p>';
echo preg_match($patern4, $string4, $matchs2);
echo '<p>';
var_dump($matchs1); //array(2) { [0]=> string(5) ".4501" [1]=> string(3) ".45" }
echo '<p>';
var_dump($matchs2); //array(2) { [0]=> string(5) ".4501" [1]=> string(3) ".45" }
//显然如果第三位小数为0,那么'\d+'就可以直接匹配'0',相比'\d*',省略一次匹配(因为是贪婪匹配,如果是懒惰匹配就不存在了);
//得出的结论就是,判断建议使用'\d*',替换建议使用'\d+';
//以上就是这一次学习的成果
相关文章推荐
- PHP正则表达式的效率 回溯与固化分组
- php学习第四章:正则表达式(四)匹配规则:分组、环视(零宽断言和负向零宽断言)
- PHP学习系列之字符串和正则表达式
- php学习之正则表达式(1)和处理中文字符串
- php学习笔记(八)正则表达式
- php入门学习知识点四 PHP正则表达式基本应用
- PHP正则表达式学习参考的文章
- PHP正则表达式学习总结--1
- PHP学习笔记九之正则表达式(进阶篇)
- PHP学习历程之——正则表达式
- 【小白笔记】PHP学习之路 (33) --正则表达式
- PHP学习之路六(php与正则表达式)
- PHP中正则表达式学习及应用(一)
- 学习php中的正则表达式,PHP正则表达式基础
- php 正则表达式详细学习
- php学习记录(正则表达式)
- php学习笔记6--php中的正则表达式函数
- php入门学习知识点四 PHP正则表达式基本应用
- PHP正则表达式学习笔记1