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


