前面我們提到過怎么查找**不是某個字符或不在某個字符類里**的字符的方法(反義)。
但是如果我們只是想要**確保某個字符沒有出現,但并不想去匹配它**時怎么辦?
例如,如果我們想查找這樣的單詞--它里面出現了字母q,但是q后面跟的不是字母u,我們可以嘗試這樣:
>[success]\\b\\w\*q\[^u\]\\w\*\\b
匹配包含**后面不是字母u的字母q**的單詞。
但是如果多做測試(或者你思維足夠敏銳,直接就觀察出來了),你會發現,如果q出現在單詞的結尾的話,像**Iraq**,**Benq**,這個表達式就會出錯。
這是因為\[^u\]總要匹配一個字符,所以如果q是單詞的最后一個字符的話,后面的\[^u\]將會匹配q后面的單詞分隔符(可能是空格,或者是句號或其它的什么),后面的\\w\*\\b將會匹配下一個單詞,
于是`\\b\\w\*q\[^u\]\\w\*\\b`就能匹配整個*Iraq fighting*。
**負向零寬斷言**能解決這樣的問題,因為它只匹配一個位置,并不**消費**任何字符。
<br/>
現在,我們可以這樣來解決這個問題:\\b\\w\*q(?!u)\\w\*\\b。
**零寬度負預測先行斷言**(?!exp),
斷言此位置的后面不能匹配表達式exp。例如:`\\d{3}(?!\\d)`
匹配三位數字,而且這三位數字的后面不能是數字;
`\\b((?!abc)\\w)+\\b`匹配不包含連續字符串abc的單詞。
<br/>
同理,我們可以用(?<!exp),
**零寬度負回顧后發斷言**來斷言此位置的前面不能匹配表達式
exp:(?<!\[a-z\])\\d{7}匹配前面不是小寫字母的七位數字。
> 請詳細分析表達式(?<=<(\\w+)>).\*(?=<\\/\\1>),這個表達式最能表現零寬斷言的真正用途。
一個更復雜的例子:`(?<=<(\\w+)>).\*(?=<\\/\\1>)`
匹配不包含屬性的簡單HTML標簽內里的內容。
(?<=<(\\w+)>)指定了這樣的**前綴**:被尖括號括起來的單詞(比如可能是<b>),然后是.\*(任意的字符串),最后是一個**后綴**(?=<\\/\\1>)。
注意后綴里的\\/,它用到了前面提過的字符轉義;\\1則是一個反向引用,引用的正是捕獲的第一組,前面的(\\w+)匹配的內容,這樣如果前綴實際上是<b>的話,后綴就是</b>了。
整個表達式匹配的是<b>和</b>之間的內容(再次提醒,不包括前綴和后綴本身)。