正则学习(十)——回溯

199 阅读2分钟

前言

正则表达式有自己的匹配原理,知道了其中原理,会加深我们对正则表达式的理解,下面我们就来学习一下正则中的回溯原理。

回溯

回溯是什么呢?简单来说回溯就是去尝试多种可能,在这过程中匹配到我们想要的结果或者匹配不到。要想理解回溯,我们可以先看一下没有回溯的匹配是什么样子的。

      const reg = /a{1,2}b/;
      const str = 'aab';
      console.log(str.match(reg))//['aa'...]

以上例子中正则是去匹配一到两次的字母a,当我们去匹配字符‘aa’的时候,首先匹配到a,因为是贪婪匹配,所以继续往下匹配,又是a,量词匹配结束,然后到字符b,得出结果。整个匹配过程是按照字符顺序匹配下来的,这就是没有回溯的匹配。 上面正则中我们把量词变一下就会变成回溯匹配:

   const reg = /a{1,3}b/;

此时我们把最大变成了3,再次匹配字符串,这时候依旧是上面分析的步骤,匹配到前两个字符'a',下面就不一样了,第三步还是会匹配a,但此时第三个是b,它会重新到匹配到两个a的情况,尝试去匹配b,刚好第三个字符时b,匹配成功。这就是所谓的回溯,面对多种情况时候,会回溯尝试各种可能。从上面的例子我们也能看到,量词、分支是常见的回溯形式,下面我们来看下这几种回溯的特点。

  • 量词:量词分为贪婪与惰性,上述例子中就是贪婪量词,对于贪婪量词,回溯的方式可能是从多到少,因为其特性就要求尽可能的去匹配;惰性量词方式是从少到多,惰性是尽可能少的匹配,最终还是为了匹配整体。
      const reg = /a{1,2}?b/;
      const str = 'aab';
      console.log(str.match(reg))

此时量词虽然是惰性的,但为了整体匹配还是字符a还是匹配了两次。

  • 分支:分支就很好理解了,就是从左到右地去试,换个分支去匹配,这也是回溯的一种形式。
      const reg = /^(a|ab)$/;
      const str = 'ab';
      console.log(str.match(reg))

当分支a不满意整体匹配时,就会换ab分支去匹配。

总结

正则在匹配字符串使用的方法就是回溯法,回溯就是多尝试,试出结果,常见的形式就是使用量词与分支。