當我們需要匹配一些字元,這些字元之前或者之後必須是特定內容的情況時,最明智的一種解決方案應該是零寬斷言了。
定義
用於給指定位置新增限定條件(斷言),在這個位置之前或者之後滿足這個限定條件時,該斷言成功。
當斷言失敗時不會再繼續匹配,當斷言匹配成功後正規表示式中的其他匹配才會繼續。
斷言部分也可以是一個正規表示式。
型別
- ?= 正向零寬匹配:匹配字元位置後的條件
簡單舉個例子:
let a = '123ab';
a.match(/\d+(?=ab)/)
//["123", index: 0, input: "123ab", groups: undefined]
複製程式碼
這個例子是匹配ab字元前面的數字,也就是需要匹配的字元後面需要滿足等於ab的條件
- ?! 正向零寬不匹配:匹配字元位置後的條件的非
簡單舉個例子
let a = '132cd';
a.match(/\d+(?!ab)/)
//["132", index: 0, input: "132cd", groups: undefined]
複製程式碼
這個和上面那個的使用一致,但個人感覺取非不夠精確,在正則裡取非的範圍有點大,所以感覺可能?=
更常用一下
舉個例子,會出現下面這種情況
let a = '132ab';
a.match(/\d+(?!ab)/)
//["13", index: 0, input: "132ab", groups: undefined]
複製程式碼
- ?<= 負向零寬匹配:匹配字元位置前的條件
簡單舉個例子
let a = '132ab';
a.match(/(?<=\d)[a-z]+/)
//["ab", index: 3, input: "132ab", groups: undefined]
複製程式碼
這個例子是為了匹配緊跟數字後面的所有小寫英文單詞,也就是為了匹配一串小寫英文字串前面必須滿足是數字的條件
- ?<! 負向零寬不匹配:匹配字元位置前的條件的非
這個與前面的第二種類似,不過是負向的,也就是字元前面應滿足斷言部分正規表示式,感覺也應該不常用,這裡不細寫了
組合使用
正向零寬和負向零寬的組合使用,可以簡化一些特定的匹配 先舉個簡單的例子 比如我需要匹配英文字母間的數字
let a = 'qee132ab';
a.match(/(?<=[a-z]+)\d+(?=[a-z]+)/)
//["132", index: 3, input: "qee132ab", groups: undefined]
複製程式碼
比如我要上面的匹配全域性使用
a = 'qee132ab324asd';
a.match(/((?<=[a-z]+)\d+(?=[a-z]+))/g)
//["132", "324"]
複製程式碼
之前做了一道題,用於匹配字元中變數x的值(比如字串為‘x=5’,匹配的結果則為5,‘fox=5’,匹配的結果則為null)
這樣的匹配使用零寬匹配可以節省很多事
a = 'fox x=5 fox';
a.match(/(?<=\bx=)\d+(?!\d+)/g)
//["5"]
複製程式碼
總結
零寬斷言主要有兩個點:
- 零寬斷言標示後面可以跟一個正則匹配方程式
如上面的例子,(?<=\bx=)
零寬標示?<=
後面的是一個正規表示式\bx=
,當然也可以是其他的任何正規表示式
- 零寬匹配完成後匹配的位置仍為當前位置
舉個例子
a = '123qwe';
a.match(/(?=\d+)\d+[a-z]+/g)
//["123qwe"]
複製程式碼
因為零寬匹配後,匹配的位置不變,零寬匹配了第0個位置,第0個位置的後面是數字,所以(?=\d+)
匹配成功,值為'',這個時候後面仍需要匹配,因為零寬匹配不移動位置,仍從第0個位置開始,這個時候需要匹配\d+[a-z]+
,這個匹配表示式匹配到了123qwe
,所以整個表示式匹配到的值為123qwe