正则表达式的运行原理详解(NFA引擎)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yx0628/article/details/82722166

正则表达式 NFA 引擎是大多主流语言使用的引擎,它以表达式为主导,更符合开发的逻辑。
理解 NFA 引擎的运行规则,是十分重要的。
我们先看一个例子:
比如下边的这行字符串

The dragging belly indicates your cat is too fat

使用这个正则来匹配的结果应该是什么呢:

fat|cat|belly|your

我们知道“或”字符表示多选分支,而且是从左到右进行匹配。那么最终结果是 fat 吗?
我们在 notepad++ 中进行一下匹配尝试:

测试结果

我们发现测试的结果,是 belly ,为什么不是最左边的 fat 呢。下面说一下正则表达式的匹配原理:
如图所示的例子,表示了正则表达式匹配的整个过程:

正则表达式运行规则

比如我们的字符串是

hellothere,happyhippo

正则表达式为

h(ello|appy)hippo

首先说一下回溯的概念:一个最简单的比方就是,我们打游戏的时候,都会有个存档点,或者叫检查点,在这里游戏会进行存档,如果在之后某时刻任务失败或者角色死亡了,我们可以从这个存档点重新开始尝试。正则中的回溯,也是这个原理。
我们开始看匹配的整个过程。
1. 开始匹配时,首先从字符串的第一个字符开始匹配,也就是 h ,正则中第一位也是 h ,继续;
2. 正则中多选分支 ello 和 appy 从左边的 ello 开始匹配,(会保留 appy 的状态,待失败返回检查点进行回溯)发现可以匹配上,继续向后匹配,正则的下一位是 h,而字符串下一位是 t ,匹配失败;此时进行回溯到 appy 的分支进行尝试,当然 appy 是没有办法匹配 ello 的,在 h 的下一位尝试就直接失败了;
3. 然后分支都走完了,没有成功的匹配。这时候,会在待匹配字符串中,后移一位,进行尝试,也就是从 e 处,继续刚刚的匹配过程。当然,我们发现,e 是没办法匹配正则的第一位 h 的。以此过程继续往复,l l o t h e r e , 一直到这个逗号处,都是无法匹配正则的;
4. 逗号失败之后,我们看到剩余的字符串是 happyhippo, 也就是下一位是 h ,可以匹配正则中的第一位 h ,然后尝试 ello 分支,显然失败要回溯到 appy,这里是可以匹配的,继续匹配 hippo,发现也是满足的。匹配成功,正则表达式匹配到了 happyhippo 子串,匹配结束。

这个过程我们明白了之后,我们再看开始的例子。我们要知道正则表达式匹配是一个一个字符作为开始进行尝试的。如果匹配失败,就往后一个字符重新整个尝试流程。
所以在 The dragging belly 这里,前边每个字符作为开始,都会尝试所有的 fat|cat|belly|your 分支,当然直到 belly 前边的空格都是匹配失败的。直到遇到 belly 的字符 b 开始时,尝试到 belly 分支,发现匹配成功。匹配结束。
NFA引擎,匹配的结果总是最靠左的第一个子串。

猜你喜欢

转载自blog.csdn.net/yx0628/article/details/82722166