小心别落入正则回溯陷阱
不知才哪儿看来的: 如果你有一个问题,你想到可以用正则来解决,那么你有两个问题了。 回溯 对于正则而言,回溯并不是必需的,这跟具体的正则引擎有关。简单地说,正则引擎分为NFA和DFA。这东西难懂且无聊,我就挑重点说。DFA(确定型有穷自动机),从匹配文本入手,从左到右,每个字符不会匹配两次,它的时间复杂度是多项式的,所以通常情况下,它的速度更快,但支持的特性很少,不支持捕获组、各种引用等等;而NFA(非确定型有穷自动机)则是从正则表达式入手,不断读入字符,尝试是否匹配当前正则,不匹配则吐出字符重新尝试,通常它的速度比较慢,最优时间复杂度为多项式的,最差情况为指数级的。但NFA支持更多的特性,因而绝大多数编程场景下(包括js),我们面对的是NFA。 NFA匹配的过程就是吃入字符,尝试匹配,如果通过,再吃入尝试;如果不通过,就吐出,回到上一个状态,因为同一个字符串在正则中可能存在一种状态不同转化路径,这时正则引擎换一个转化状态进行尝试,如果通过,继续吃入字符,否则继续吐出字符,回到再上一个状态。这种尝试不成功就返回上一状态的过程,我们称为回溯。正则匹配的性能好坏,就看回溯的情况,回溯越多,性能越差。 为了说清楚这个问题,我们做一个实验,用 a(acd|bsc|bcd) 这个正则来对“abcd”这个字符串进行匹配。 截图上方是正则表达式,右侧是要匹配的文本,左侧是匹配的过程。 可以看到