正则表达式有 [正反] 向 [肯否] 定预查四种预查形式

(?:pattern)

匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。


正向

从右往左去查询

正向肯定

(?=pattern)

正向肯定预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

正向否定

(?!pattern)

正向否定预查,在任何不匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始


反向

从左往右去查询

反向肯定

(?pattern)

反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。

反向否定

(?<!pattern)

反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。

案例

案例一

/(?<=200|300)d(?<=d)ows/gim.exec("Win200dows")

这段正则的含义是啥?
首先是反向,即先从左往右看

  • (?<=200|300) 当前的开头是否是 200 或 300
  • 匹配到 200dows,抛弃 200
  • 匹配 d
  • (?<=d)ows 匹配到 ows,抛弃 d
    即当前会匹配到 dows
    记住,所有的在预查中的值都会被抛弃

案例二 - 组合

组合使用 正向、反向

/(?<=200|300)d(?=ow)ows/gim.exec("Win200dows")

这段代码同时使用了 反向预查,正向预查。
依旧能查出来结果为 dows

案例三 - 转化

/(?<!200)dows/

如何转化成正常的正则表达式呢?因为 lookbacks 在 Safari on iOS 上是不能用的。
可以转化为

/(200)?dows/

然后在通过后面的逻辑,判断是否存在 200 即可。
不存在、则表明和上面等价。
性能可能会差,但这是没有办法的办法。

附录
https://zekizz.github.io/python/regex-preview/