javascript正則--零寬斷言--案例解析

m53469發表於2021-09-09

理解這個案例需要一點點正則基礎,要對js的正則有基礎的認識與瞭解,如果沒有的話,建議先看完慕課網站的相關js正則課程再來.
下面這個正則要求密碼長度最少12位,包含至少1個特殊字元,2個數字,2個大寫字母和一些小寫字母。
reg=/(?=^.{12,25}$)(?=(?:.?d){2})(?=.[a-z])(?=(?:.?[A-Z]){2})(?=(?:.?[!@#$%()_+^&}{:;?.]){1})(?!.s)[0-9a-zA-Z!@#$%()_+^&]$/
看著就很複雜T-T,如果你有一些基礎,就應該能認出裡面的各個符號的含義.

首先來了解兩個概念:

1.正則物件的屬性lastIndex
是當前表示式匹配內容的最後一個字元的下一個字元的下標(位置).這個屬性的作用非常大,他的主要作用就是回溯標記.
比如在正則有分支的情況下,第一條分支匹配失敗,就會回溯到上一個匹配成功的結果的標記處,再嘗試匹配其他分支.
比如在使用全域性匹配時,第一輪匹配到一個內容,匹配結束,第二輪開始匹配的位置就是從lastIndex開始.
也就是說lastIndex是隨著匹配結果變化的

2.零寬斷言
本來是叫前瞻(後顧js不支援啦),因為前瞻有個非常重要的特性--即斷言匹配時不需要被捕獲,不必對應到匹配結果裡,只是作為匹配時的條件.而所謂的零寬的真正意義就體現在這裡---它工作時不會改變lastIndex屬性的值.

現在把兩個概念結合一下:捕獲性的斷言會改變lastIndex屬性的值,而零寬斷言則不會改變不會改變lastIndex屬性的值.理解這一點是理解上面那個例子的關鍵.

下面開始解析例子
例子裡有很多的.*?的組合,我們先從這裡開始

. 表示任意字元

*表示可以匹配任意次數

?表示最多匹配一次

三個合起來:對任意個()連續任意字元(.)匹配最多一次(?),也就是說不管有什麼字元,不管有沒有字元都能被.?匹配上.

以例子裡的這一段(?=(?:.?d){2})為例,
先拆分出(?:.
?d) : 匹配一個數字,不管數字前是什麼,也不管數字前有沒有都能匹配上.

加上次數(?:.*?d){2},匹配第二次時從匹配到的第一個數字的下一位開始匹配(lastIndex屬性).(這裡其實跟零寬斷言沒什麼關係)

再回到整體(?=(?:.*?d){2}):從第零為開始匹配,至少有兩個數字,不管這兩數字在什麼位置.

這個例子基本上就是幾個前瞻組成的,零寬斷言表示的只是匹配的位置,由於前瞻的前面沒有用字元提出匹配內容,所以例子裡的每一個前瞻都是從字串最開始的地方開始匹配.

例子裡的其他部分解釋起來與(?=(?:.?d){2})大同小異,理解了(?=(?:.?d){2}),同樣的道理往其他幾個上一套,整體就出來了

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2819/viewspace-2798724/,如需轉載,請註明出處,否則將追究法律責任。

相關文章