在笔记回溯和固态分组时,先介绍什么是反向引用
//反向引用
//示例
复制代码
1
2
3
4$string = 'abcdebbcde'; $patern = '/([ab])1/'; preg_match($patern, $string, $matchs); var_dump($matchs);
复制代码
1
2
3
4
5
6
7//分析://对于'([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'.至此匹配结束.
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16//注意://在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);
//回溯
//示例:(和注释(学习笔记__可能有错误的地方))
复制代码
1
2echo "n"; $string3 = 'abbcbbcdef';
复制代码
1//每一次'.+',都会留下一个回溯点
复制代码
1
2
3
4
5
6
7
8$patern4 = '/a.+c/'; //贪婪匹配,尽可能匹配满足要求的字符串最长(即是字符串越短越好),(实现方法:倒序回溯匹配),所以回溯了3次 preg_match($patern4, $string3, $matchs4); var_dump($matchs4); echo '<p>'; $patern5 = '/a.+?c/'; //懒惰匹配,尽可能匹配满足要求的字符串最短(即是字符串越短越好)(实现方法:正序回溯匹配),所以回溯了2次 preg_match($patern5, $string3, $matchs5); var_dump($matchs5); //因此,回溯的效率和懒惰匹配和贪婪匹配没有关系,只是匹配的目标字符串长度不同
//固态分组:目的为了减少回溯次数
//示例:(有注释(学习笔记__可能有错误的地方))
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39//案例概述:比如要处理一批数据,原来格式为123.456,后来因为浮点数显示问题,部分数据格式变为123.456000000789这种,要求做到只保留小数点后面2-3位,但是,最后一位不能为0 echo '<p>'; $string4 = '123.456'; $patern1 = '/(.dd[1-9]?)d*/'; $patern2 = '/(.dd[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 = '/(.dd(?>[1-9]?))d+/'; $patern4 = '/(.dd(?>[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内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复