首頁 > 軟體

正規表示式(?=)正向先行斷言實戰案例

2022-11-21 14:01:52

最近在練習正規表示式,遇到了一道很有意思的題,題目如下

我的答案如下

(?=.*?[A-Z])(?=.*?d)(?=.*?[a-z]).{8,}

對於這個答案的理解得先從正向先行斷言的語法開始說起。

正向先行斷言的語法格式如下

expression1(?=expression2)
# 查詢expression2前面的expression1

當然這個expression1也可以不寫(也就是為空白符

例子如下

該正規表示式的意思為:尋找abcd字串前的123456字串。

這裡也提一個有意思的地方

以上兩個正規表示式中的/d+/gm/123456/gm其實都能匹配123456這個字串,但在正向先行斷言中,前者會匹配每個數位前面的空白符,後者將123456字串當成一個整體,只匹配這個整體前面的空白符。

這裡面的原理還需要等我研究一下,估計是跟底層程式碼的實現有關,我猜測是(?=d+)在匹配的時候會將每個數位單獨提取出然後向前比較。

那麼回到該題的答案中,先讓我們看看 (?=.*?[A-z]) 是什麼意思。

很明顯上圖匹配了大寫字母A前面的所有空白符

其中的.*?[A-Z]代表大寫字母及其前面的字串且為懶惰匹配

那麼(?=.*?[A-Z])(?=.*?d)的意思就有點套娃了,按我的理解就是對於(?=.*?d)而言把(?=.*?[A-Z])當成expression1,對於(?=.*?[A-Z])而言就是把空白符當成expression1

那麼這個正規表示式就表示為:在尋找到每個大寫字母前面的所有空白符的基礎上還要滿足:這些空白符都在每個數位前面的所有空白符這個匹配集合中。相當於是兩個空白符集合的交集

所以(?=.*?[A-Z])(?=.*?d)(?=.*?[a-z])相當於是每個大寫字母、小寫字母、數位前面的所有空白字元的交集

 而後面的.{8,}則匹配這些空白字元后面至少八位字元(貪婪匹配)

附:先行否定斷言

x(?!y)稱為先行否定斷言(Negative look-ahead),x只有不在y前面才匹配,y不會被計入返回結果。比如,要匹配後面跟的不是百

分號的數位,就要寫成/d+(?!%)/。

/d+(?!.)/.exec('3.14') // ["14"]
// ["14"]

上面程式碼中,正規表示式指定,只有不在小數點前面的數位才會被匹配,因此返回的結果就是14。

“先行否定斷言”中,括號裡的部分是不會返回的。

var m = 'abd'.match(/b(?!c)/);
m // ['b']

上面的程式碼使用了先行否定斷言,b不在c前面所以被匹配,而且括號對應的d不會被返回。

總結

到此這篇關於正規表示式(?=)正向先行斷言的文章就介紹到這了,更多相關正規表示式正向先行斷言內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com