正则表达式之 "正向否定预查"

这篇文章写的不够透彻.. 需要重新写一下.

记录一些比较有技巧性的用法

正向否定/肯定预查

  • 匹配以/wiki/开头, 后面不包含:, 的字符串. 写法如下:
    ^(/wiki/)((?!:).)*$
    前面的^(/wiki/)是比较好理解的, 就是以/wiki/开头, 但是后面的((?!:).)*是什么意思呢?
    这就需要先了解一个PCRE表达式: (?!pattern)正向否定预查(negative assert), 维基百科中的解释是:
  • 正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
  • 正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。

x(?!:)意思就是x的后面没有:, 那么如果这么说的话, 他应该可以成功匹配形如xy, xx等字符串了? 并不是的. 注意上文维基百科解释中的最后一句话, 预查不消耗字符, 也就是说(?!:)只是表达了后面不能跟:, 但是并不代表xy中的y, 所以正确的表达式是形如x(?!:).x(?!:)\w这种, 让.\w来代表xy中的y. 具体可以看下图:

无法匹配

成功匹配

现在, 应该了解了(?!:).的意义了, 即一个不是:的字符, 然而我们要匹配的是零个一个或多个不是:的字符串, 那么应该怎么做呢? (?!:).*或者(?!:).+么, 这样显然也是不行的. 这样只能保证第一个不是:. 正确的应该是((?!:).)*. 把(?!:).包在一起. 在一起之后我们可以把他俩看成描述一个字符的表达式, 就是我们刚刚说的一个不是:的字符. 那么在其后跟着个*就代表了零个或多个不是:的字符.
那么这个表达式稍微复杂的部分就解释完啦.

参考
维基百科


了解如下表达式:

匹配某字符串, 其后面是/不是xxx的:
(?!) - negative lookahead
(?=) - positive lookahead
匹配某字符串, 其前面是/不是xxx的:
(?<=) - positive lookbehind
(?<!) - negative lookbehind
(?>) - atomic group

字符串例子: foobarbarfoo

  • 匹配后面是`bar`的字符串`bar`

    同上, 匹配后面是`barfo`的字符串`bar`
  • 匹配后面不是`bar`的字符串`bar`

.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 正则匹配 理论 正则表达式由常量和算子组成,它们分别指示字符串的集合和在这些集合上的运算 正则匹配的基本概念 .:...
    Hqmm阅读 3,294评论 0 0
  • 忘了从哪收集的资料了,放这儿,以备不时之需。 只能输入数字:"^[0-9]*$"。 只能输入n位的数字:"^\d{...
    study_monkey阅读 5,232评论 0 7
  • 一、什么是正则表达式 正则表达式,又称正规表示法,是对字符串操作的一种逻辑公式。正则表达式可以检测给定的字符串是否...
    木马不在转阅读 6,311评论 8 21
  • 参考原文:http://www.admin10000.com/document/5944.html 一、什么是正则...
    Louis_hey阅读 4,272评论 0 1
  • 一、什么是正则表达式 正则表达式,又称正规表示法,是对字符串操作的一种逻辑公式。正则表达式可以检测给定的字符串是否...
    Helen_kay阅读 7,634评论 0 2