1. 程式人生 > >深入理解正則表示式的環視

深入理解正則表示式的環視

從Zjmainstay的深入理解正則表示式高階教程中擷取的一部分內容:
環視(斷言/零寬斷言)

環視,在不同的地方又稱之為零寬斷言,簡稱斷言。 
用一句通俗的話解釋: 
環視,就是先從全域性環顧一遍正則,(然後斷定結果,)再做進一步匹配處理。 
斷言,就是先從全域性環顧一遍正則,然後斷定結果,再做進一步匹配處理。

兩個雖然字面不一樣,意思卻是同一個,都是做全域性觀望,再做進一步處理。

環視的作用相當於對其所在位置加了一個附加條件,只有滿足這個條件,環視子表示式才能匹配成功

環視主要有以下4個用法: 
(?<=exp) 匹配前面是exp的資料 
(?<!exp)

 匹配前面不是exp的資料 
(?=exp) 匹配後面是exp的資料 
(?!exp) 匹配後面不是exp的資料

示例四: 
(?<=B)AAA 匹配前面是B的資料,即BAAA匹配,而CAAA不匹配 
(?<!B)AAA 匹配前面不是B的資料,即CAAA匹配,而BAAA不匹配 
AAA(?=B) 匹配後面是B的資料,即AAAB匹配,而AAAC不匹配 
AAA(?!B) 匹配後面不是B的資料,即AAAC能匹配,而AAAB不能匹配

另外,還會看到(?!B)[A-Z]

這種寫法,其實它是[A-Z]範圍裡,排除B的意思,前置的(?!B)只是對後面資料的一個限定,從而達到過濾匹配的效果。

因此,環視做排除處理是比較實用的,比如,示例五:

需求:字母、數字組合,不區分大小寫,不能純數字或者純字母,6-16個字元。
通用正則:^[a-z0-9]{6,16}$    字母數字組合,6-16個字元
    排除純字母:(?!^[a-z]+$)
排除純數字:(?!^[0-9]+$)
    組合起來:(?!^[a-z]+$)(?!^[0-9]+$)^[a-z0-9]{6,16}$

注意,環視部分是不佔寬度的,所以有零寬斷言的叫法。 
所謂不佔寬度,可以分成兩部分理解: 
1、環視的匹配結果不納入資料結果 
2、環視它匹配過的地方,下次還能用它繼續匹配。

如果不是環視,則匹配過的地方,不能再匹配第二次了。

上面示例四體現了:環視的匹配結果不納入資料結果,它的結果:


 
  1. (?<=B)AAA 源串:BAAA 結果:AAA
  2. (?<!B)AAA 源串:CAAA 結果:AAA
  3. AAA(?=B) 源串:AAAB 結果:AAA
  4. AAA(?!B) 源串:AAAC 結果:AAA

而示例五體現了:環視它匹配過的地方,下次還能用它繼續匹配 
因為,整個匹配過程中,正則表示式一共走了3次字串匹配,第一次匹配不全部是字母,第二次匹配不全部是數字,第三次匹配全部是字母數字組合,6-16個字元。


 
  1. 擴充套件部分:
  2. `[A-Z](?<=B)` [A-Z]範圍等於B
  3. `[A-Z](?<!B)` [A-Z]範圍排除B
  4. `(?!B)[A-Z]` [A-Z]範圍排除B

附: js不支援(?<=exp) 和 (?<!exp) 語法