这篇文章写的不够透彻.. 需要重新写一下.
记录一些比较有技巧性的用法
正向否定/肯定预查
- 匹配以
/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`
.