几个认识:
- 环视的正则表达式是用来匹配一个隐式位置的。
- 一个完整的环视正则表达式格式为(?=pattern),其中pattern为要匹配隐式位置的正则表达式。
- 环视正则表达式要包含到括号内。
显式位置和隐式位置
上图非常直观,字符的位置就是显式位置,字符之间的空隙就是隐式位置。
在正则表达式中,最常用的匹配隐式位置的元字符就是 ^
和 $
了,用上面的字符串minecraft
来举例,其匹配的位置并不是字符的位置,而是隐式位置:
另外还有一个元字符来匹配单词的开头或结尾:\b
此字符的官方释义为:
\b 匹配这样的位置:它的前一个字符和后一个字符不全是(一个是,一个不是或不存在) \w。
当然这小白一看就懵逼,作者 沧海一滴 中关于\b
博客中有一句话就解释的很明白:
“隐式位置” \b,匹配这样的位置:它的前一个“显式位置”字符和后一个“显式位置”字符不全是 \w。
我们知道\w
代表 [a-z][A-Z]
(js中不代表中文),所以\b
所匹配到的隐式位置,其两边的显式位置必须有一边为字母,一边为空格 换行或者是.
。
有了这个元字符我们就可以很轻易的匹配一篇英文文章的所有单词:(背景色为蓝色的字符是匹配到的字符)
顺序环视 (?=pattern)
先不要管什么是顺序环视,直接上一张图来看看此表达式匹配到了一个什么位置(以/(?=cra)/
的例子为例):
上图可以看到:其表达式 匹配到了目标字符串 并且 返回 了一个隐式位置,其位置在字符位置 c
的前面。此时这个表达式就代表一个隐式位置
在执行表达式时,引擎将遍历每一个字符的缝隙(隐式位置),如果当前的隐式位置从左往右正好匹配到了cra 子字符串,那么就返回这个隐式位置。
之前我们都知道 ^
元字符是用来匹配字符串的开头的隐式位置,并且我们也经常用此元字符来匹配开头字符串;例如,我想匹配开头为 mine
或 But
的字符串(匹配时全局模式,也就是说每行都是独立的一个字符串):
图中的表达式也就是在告诉表达式引擎 “我需要匹配隐式位置在字符串的开头位置并且后接Mine或But”
当我们拿到了环视表达式的位置,也就是告诉表达式引擎 “我需要匹配隐式位置在目标字符串 cra 的开头位置”
我们可以根据这个环视返回的位置来匹配两侧的字符串了;“我只想匹配子字符串 cra 的开头隐式位置的左侧字符 e”:
只要有了上图的表达式,那么其他位置的字符 e 将不会被匹配
再例如 “我只想匹配 子字符串 cr 的开头位置左侧的 /\w+/ 或空格”:
这里的 空格 和 /\w+/ 必须括起来,否则 环视表达式只应用于 /\w+/
环视不消耗字符:因为环视最终只返回位置,肯定不消耗字符
倒第二个例子:“我只想匹配 子字符串 cra 的开头位置右侧的 cr 字符串”:
最后一个例子,我只想匹配 子字符串 cr 的开头位置右侧的 cra 或 cre 的 字符串:
再次强调,环视只匹配并返回一个隐式位置,如果上图的例子看不明白请自己斟酌这句话。
注意:环视只匹配位置,不匹配字符,所以无法使用捕获组来返回其字符串
结论:所谓顺序环视也就是匹配目标字符串,并返回目标字符串开头的隐式位置,因为从此隐式位置从左往右匹配 才可以匹配到环视表达式的目标字符串。
逆序环视(?<=pattern)
读懂了顺序环视,逆序环视就极其简单,直接上图,一目了然:
在执行表达式时,引擎将遍历每一个字符的缝隙(隐式位置),如果当前的隐式位置从右往左正好匹配到了cra 子字符串,那么就返回这个隐式位置。
结论:所谓逆序环视也就是匹配目标字符串,并返回目标字符串结尾的隐式位置,因为从此隐式位置从右往左匹配 才可以匹配到环视表达式的目标字符串
有了这个位置就可以匹配其左右显式位置的字符串了
例子: “我只想匹配 字符i 之前的 \w+字符串”
否定环视(?!pattern)(?<!pattern)
理解了以上知识后,就可以瞬间理解否定环视,否定环视也有顺序和逆序,书写时不同点只是把 = 号 换成了 ! 号 在众多编程语言中!=都表示不等于
,==都表示等于;而正则表达式中,= 等于肯定 ;!等于否定。
例子:正则表达式 /minecraft(?!crepper)/
其意思为匹配子字符串 minecraft 并且 紧接着的字符串不能是 crepper
如果看不懂上面的意思,建议此文章再看一遍
结束
引用文章:
https://blog.csdn.net/az44yao/article/details/108333671?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-2&spm=1001.2101.3001.4242
https://www.cnblogs.com/softidea/p/4925577.html