1. 程式人生 > >正則匹配之零寬斷言

正則匹配之零寬斷言

當我們需要匹配一些字元,這些字元之前或者之後必須是特定內容的情況時,最明智的一種解決方案應該是零寬斷言了。

定義

用於給指定位置新增限定條件(斷言),在這個位置之前或者之後滿足這個限定條件時,該斷言成功。

當斷言失敗時不會再繼續匹配,當斷言匹配成功後正則表示式中的其他匹配才會繼續。

斷言部分也可以是一個正則表示式。

型別

  1. ?= 正向零寬匹配:匹配字元位置後的條件

簡單舉個例子:

let a = '123ab';
a.match(/\d+(?=ab)/)
//["123", index: 0, input: "123ab", groups: undefined]
複製程式碼

這個例子是匹配ab字元前面的數字,也就是需要匹配的字元後面需要滿足等於ab的條件

  1. ?! 正向零寬不匹配:匹配字元位置後的條件的非

簡單舉個例子

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]
複製程式碼
  1. ?<= 負向零寬匹配:匹配字元位置前的條件

簡單舉個例子

let a = '132ab';
a.match(/(?<=\d)[a-z]+/)
//["ab", index: 3, input: "132ab", groups: undefined]
複製程式碼

這個例子是為了匹配緊跟數字後面的所有小寫英文單詞,也就是為了匹配一串小寫英文字串前面必須滿足是數字的條件

  1. ?<! 負向零寬不匹配:匹配字元位置前的條件的非

這個與前面的第二種類似,不過是負向的,也就是字元前面應滿足斷言部分正則表示式,感覺也應該不常用,這裡不細寫了

組合使用

正向零寬和負向零寬的組合使用,可以簡化一些特定的匹配 先舉個簡單的例子 比如我需要匹配英文字母間的數字

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"]
複製程式碼

總結

零寬斷言主要有兩個點:

  1. 零寬斷言標示後面可以跟一個正則匹配方程式

如上面的例子,(?<=\bx=)零寬標示?<=後面的是一個正則表示式\bx=,當然也可以是其他的任何正則表示式

  1. 零寬匹配完成後匹配的位置仍為當前位置

舉個例子

a = '123qwe';
a.match(/(?=\d+)\d+[a-z]+/g)
//["123qwe"]
複製程式碼

因為零寬匹配後,匹配的位置不變,零寬匹配了第0個位置,第0個位置的後面是數字,所以(?=\d+)匹配成功,值為'',這個時候後面仍需要匹配,因為零寬匹配不移動位置,仍從第0個位置開始,這個時候需要匹配\d+[a-z]+,這個匹配表示式匹配到了123qwe,所以整個表示式匹配到的值為123qwe