零宽度断言的关键知识点

前端之家收集整理的这篇文章主要介绍了零宽度断言的关键知识点前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

正则表达式的匹配是从字符串的开头到字符串的结尾,在引擎看来,字符串 “str” 是这个样子的形式:^s@t@r$,^ 表示字符串开头的位置,即第一个字符之前的位置,@ 表示字符之间的位置,$ 表示字符串末尾的位置,即最后一个字符之后的位置。匹配是从一个位置移动到下一个位置,假设正则表达式为 tr,我们在字符串 “str” 中寻找其匹配,首先,引擎会指向 ^ 位置,将 t 与当前字符 s 做对比(”当前字符”是指当前位置之后的第一个字符),发现不符,引擎便指向 下一个位置,即 @ 位置,即字符 s 之后的位置,然后继续用 t 与当前字符 t 做比较,发现相同,引擎继续移向下一个位置,即第二个 @ 位置,并用 r 与当前字符 r 做比较,发现相同,至此,正则匹配结束。

位置的概念是很重要的,尤其在理解零宽度断言的时候,因为零宽度断言就是判断某个”位置”是否符合条件,举个简单例子,假设正则表达式为 s(?=t),我们依然在字符串 “str” 中寻找其匹配,首先需要注意的是,s(?=t) 只匹配一个字符,因为(?=t)的宽度为”零”。匹配过程是这样的:引擎首先指向 ^ 位置,然后用 s 与当前字符 s 做比较,发现相同,然后引擎指向第一个 @ 位置,在该位置上应用零宽度断言 (?=t) 判断当前字符 t 是否等于 t,发现等于,则匹配成功,最后的匹配结果是 s 。下面对正则表达式稍做些变形,观察匹配结果是什么:

变形1:正则表达式为 s(?!t),引擎的匹配过程如下:
引擎首先指向 ^ 位置,然后用 s 与当前字符 s 做比较,发现相同,然后引擎指向第一个 @ 位置,在该位置上应用零宽度断言 (?!t) 判断当前字符 t 是否不等于 t,发现等于,说明匹配失败,最终结果是没有找到任何匹配。

变形2:正则表达式为 s(?=t)r,引擎的匹配过程如下:
引擎首先指向 ^ 位置,然后用 s 与当前字符 s 做比较,发现相同,然后引擎指向第一个 @ 位置,在该位置上应用零宽度断言 (?=t) 判断当前字符 t 是否等于 t,发现等于,说明匹配成功,接着引擎在当前位置匹配 r (注意,这里的当前位置仍然是第一个 @ 位置,因为 (?=t) 的宽度为0,所以引擎在匹配完 (?=t) 后没有移动引擎指针),所以接着引擎会用 r 与当前字符 t 做比较,发现匹配失败,最终匹配结果也是没找到任何匹配。

变形3:正则表达式为 s(?=t)t,引擎的匹配过程如下:
引擎首先指向 ^ 位置,然后用 s 与当前字符 s 做比较,发现相同,然后引擎指向第一个 @ 位置,在该位置上应用零宽度断言 (?=t) 判断当前字符 t 是否等于 t,发现等于,说明匹配成功,接着引擎在当前位置匹配 t (注意,这里的当前位置仍然是第一个 @ 位置,因为 (?=t) 的宽度为0,所以引擎在匹配完 (?=t) 后没有移动引擎指针),所以接着引擎会用 t 与当前字符 t 做比较,发现匹配成功,最终匹配结果是 st 。

变形4:正则表达式为 (?=s)t,引擎的匹配过程如下:
引擎首先指向 ^ 位置,然后应用零宽度断言 (?=s) 用 s 与当前字符 s 做比较,发现相同,然后引擎停留在当前位置,并 判断当前字符 s 是否等于 t,发现不等于,说明匹配失败,最终匹配结果是没有找到任何匹配 ,其实上述正则表达式永远都无法匹配成功。

变形5:正则表达式为 (?=s)s,引擎的匹配过程如下:
引擎首先指向 ^ 位置,然后应用零宽度断言 (?=s) 用 s 与当前字符 s 做比较,发现相同,然后引擎停留在当前位置,并 判断当前字符 s 是否等于 s,发现不等于,说明匹配成功,最终匹配结果是:s

最后举一个稍微复杂点的例子:字符串为 “a stop b”
正则表达式1:.*(?=\bstop\b),匹配结果:”a ” (注意,a 的后面还有个空格)
正则表达式2:(?=\bstop\b).*,匹配结果:”stop b”

特别需要理解的其实就是一点:零宽度断言是判断”位置”是否满足条件,当零宽度断言完成匹配后,引擎会停留在原来的位置,接着进行下一步的匹配。

猜你在找的正则表达式相关文章