预搜索/零宽度的缝隙匹配的介绍

参考:
http://www.regular-expressions.info/lookaround.html
http://hi.baidu.com/13639966396/blog/item/14ef86867862513a67096ec5.html
http://www.regexlab.com/zh/regref.htm

预搜索
(?=exp)
(?!exp)
(?<=exp)
(?<!exp)

下面的说明很容易让人头晕,不看也罢,我将以另一种方式对它们的作用和用法进行说明
(?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(?<!exp) 匹配前面不是exp的位置

有的资料上翻译为零宽度断言,我习惯于预搜索这种叫法,前两个为正向预搜索,后两个为反向预搜索,当然还有其它翻译,其实都是一个意思,知道就行,不必在意

这四种表达式,它们与非捕获的相同之处在于,并不将匹配到的结果保存到捕获组,不同之处在于,非捕获组匹配到的内容,虽然不保存到捕获组,但却是在结果$0实实在在存在的,而以上四种表达式所匹配到的内容,一般来说,是不存在$0内的,所以说它们匹配的结果是零宽度的

更好的理解方式,是把它们作为附加条件,而不是正则表达式的组成部分

为了更好的说明,先说一下“缝隙”的概念,“缝隙”是零宽度的,它只是字符串中的一个位置,而不是实际的字符,如字符串“ab”,在“a”前面,“a”和“b”中间,还有“b”后面,分别有一个“缝隙”,也就是整个字符串有三个“缝隙”

(?=exp) 在所在“缝隙”的后面附加一个条件,也就是“缝隙”后面必须能够匹配exp的内容
(?!exp) 在所在“缝隙”的后面附加一个条件,也就是“缝隙”后面必须不能够匹配exp的内容
(?<=exp) 在所在“缝隙”的前面附加一个条件,也就是“缝隙”前面必须能够匹配exp的内容
(?<!exp) 在所在“缝隙”的前面附加一个条件,也就是“缝隙”前面必须不能够匹配exp的内容


举例说明如下:
<[^>]*> 表达式任意html标签

附加一个条件
<(?!img)[^>]*>
这个就表示除 <img...> 标签外的所有标签


再看一下 <(?!img)[^>]*> 这个正则表达式
(?!img)所在的“缝隙”是“ <”和它后面的第一个字符之间的“缝隙”,它表示的意思就是,在这个“缝隙”的后面,不能是img,整个表达式的意思也就是不匹配 <img...> 标签

同理, <(?=img)[^>]*> 表示只匹配 <img...> 标签

(?<=<a[^>]>) <img[^> ]*> 表示只匹配前面为 <a> 标签的 <img...> 标签
快乐渡过每一天,减肥坚持每一天