正则表达式匹配回溯

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则表达式匹配回溯相关的知识,希望对你有一定的参考价值。



正则表达式匹配回溯:
一.基本概念:
NFA引擎的正则表达式会依次处理各个子表达式或者组成元素,遇到需要在两个都可能进行成功匹配的子表达式或者组成元素之间进行选择的时候,会首先选择其一,同时会记录另一个的状态,以备后面使用。
注意:这里所说的子表达式并非只有用小括号括起来的表达式,而是正则表达式中的任意匹配单元。
二.需要回溯的情况:
无论是哪一种选择,如果本身匹配成功,而且正则表达式余下的部分也能够成功匹配的话,那么整个匹配就成功了,如果正则表达式当前选择或者后面的部分无法匹配成功,那么正则表达式引擎会回溯到之前作出选择的地方,然后选择其他备用的分支继续匹配。
三.回溯演示:
下面对正则表达式回溯通过一个实例代码进行一下分解,建议首先参阅正则表达式匹配原理一章节。 
代码实例如下:
var str="I love antzone";
var reg=/ant(tone|moze|zone)/g;
console.log(str.match(reg));

以上正则表达式可以匹配字符串中的"antzone"。在正则表达式中有分支选项,这里就会用到回溯了。
下面进行一下分解:
首先正则表达式字符串中的字符"a"会获得控制权,从位置0处开始匹配,它并不能够匹配字符"a",然后正则引擎推动字符"a"从下一个位置开始匹配,一直到字符串中的字符"a"才能够匹配成功,然后正则表达式的控制权传给字符"n",匹配字符"n"成功,然后控制权传递给字符"t",匹配字符"t"成功。这个时候后面会遇到三个分支,正则引擎会选择其中之一进行匹配,其他的则作为备用,首先选择"tone"进行匹配,匹配失败,但是此次失败并不说明这个匹配会失败,因为还有可能匹配成功的备用选项存在,这个时候正则表达式会回溯到"tone"开始匹配的位置,再使用"moze"进行匹配,最后最后一个选项分支可以匹配成功。
可能上面的稍显复杂了,下面来个简单的再回头看上面的可能就容易理解了。
代码如下:

 

var str="ac";
var reg=/a(d|c)/g;
console.log(str.match(reg));

 图示如下:

<ignore_js_op>技术分享
分解如下:
首先正则表达式中的字符"a"获得控制权,从位置0处开始匹配,它可以匹配字符串中的字符"a",然胡控制权让渡给"(d|b)",这是一个选择分支,首先使用第一个选项"d"从位置1处开始匹配,并且另一个选项"b"作为一个备选状态。字符"d"并不能够匹配字符"b",所以进行回溯,也就是再回到位置1处使用备选状态进行匹配。回溯原理大致如此,只是有的复杂有的简单而已。

 

以上是关于正则表达式匹配回溯的主要内容,如果未能解决你的问题,请参考以下文章

正则进阶之,回溯, (贪婪* 非贪婪+? 独占++)三种匹配量词

第977期正则表达式回溯法原理

如何优化我的回溯解决方案以匹配正则表达式?

正则表达式 之 回溯引用:前后一致匹配

带有`\R`的Java-8 正则表达式否定回溯

非固定长度的正则表达式负回溯