解惑正規表示式中的捕獲

2022-01-24 13:10:04 字數 3070 閱讀 5830

讀jquery原始碼,其中不可避免的要弄明白正規表示式,在此對非捕獲組(non-capturing)進行了一些梳理。

(?:x)

(?=x)

(?<=x)

(?!x)

(?要書明白捕獲,就要先從分組開始。重複單字元我們可以使用限定符,如果重複字串,用什麼呢? 對!用小括號,小括號裡包裹指定字表示式(子串),這就是分組。之後就可以限定這個子表示的重複次數了。

那麼,什麼是捕獲呢?使用小括號指定乙個子表示式後,匹配這個子表示式的文字(即匹配的內容)可以在表示式或者其他過程中接著用,怎麼用呢?至少應該有個指標啥的引用它吧? 對!預設情況下,每個分組(小括號)會自動

擁有乙個組號,從左到右,以分組的左括號為標誌,第乙個出現的分組組號為1,後續遞增。如果出現巢狀,

例如:「aabcd」

採用正則(a(b))(c)match 結果入下:

分組捕獲

$1(group1)

ab$2(group2)

b$3(group3)

c繼續漲姿勢。

一、(?:)非捕獲組走起。

由下面乙個例子引發對非捕獲組的學習。

有兩個金額:6000¥ 和 1000$。

需求是得到金額和貨幣種類。

『廢話少說,多用正則』:

(\d+)+([$¥])

輸出結果為:

ok,滿足了要求。這裡的正則分成了兩個組,乙個是(d+),乙個是(¥$),前乙個組($1)匹配金額,後乙個組($2)匹配貨幣種類。

現在,需求變了!! 我需要這個正則同時可以匹配浮點數小數點前面的整數。如10010.86¥,提煉出 10010 和 ¥。

那麼正則如下:

(\d+)(\.?)(\d)([$¥])
這裡用括號分了四組,所以要輸出金額的整數部分和種類,要分別輸了$1,$4了。如果輸出部分和正則是分開的,我希望只修改正則而不去修改輸出部分的**,也就是還是用$1,$2作為輸出。由此可以引出非捕獲組(?:)。

把前面的正則修改為:

(\d+)(?:\.?)(?:\d+)([¥$])$
這樣,還是用$1,$2做為輸出,同樣輸出了 10010 和 ¥

這個正則的中間兩個組用到的就是非捕獲組(?:),它可以理解為只分組而不捕獲。

二、(?=)和(?<=) 前後查詢

有的資料把它們叫做肯定式向前查詢和肯定式向後查詢;

有的資料也叫做肯定順序環視和肯定逆序環視。

1、直接看下面的例子:

[0-9a-z](?=aa) var str = "12332aa438aaf";
match list:132

238這個正則的意思是:匹配這麼乙個字串,它要滿足:是兩位字元(數字,或字母),且後面緊跟著兩個a。

分析一下:

32aa 這個子串滿足這個條件,所以可以匹配到,又因為 (?=) 的部分是不捕獲的,所以輸出的只是 32,不包括aa。同理 38aa 也匹配這個正則,而輸出僅是 38。

再深入看一下:

當str第一次匹配成功輸出 32 後,程式要繼續向後查詢是否還有匹配的其它子串。那麼這時應該從 32aa 的後一位開始向後查詢,還是從 32 的後一位呢?也就是從索引 5 開始還是從 7 開始呢?有人可能想到是從 32aa 的下一位開始往後找,因為 32aa 匹配了正則,所以下一位當然是它的後面也就是從 4 開始。但實際上是從 32 的後一位也就是第乙個 a 開始往後找。原因還是 (?=) 是非捕獲的。

查閱api文件是這麼注釋的:

(?=x) x, via zero-width positive lookahead

可見zero-width(零寬度)說的就是這個意思。

現在,把字串寫的更有意思些:str = "aaaaaaaa";

看一下它的輸出: aa aa aa

分析一下:

這個字串一共有8個a。

第一次匹配比較容易找到,那就是前四個:aaaa ,當然第三和第四個 a 是不捕獲的,所以輸出是第一和第二個a;

接著繼續查詢,這時是從第三個a開始,三到六,這4個a區配到了,所以輸出第三和第四個a;

接著繼續查詢,這時是從第五個a開始,五到八,這4個a區配到了,所以輸出第五和第六個a;

接著往後查詢,這時是從第七個a開始,顯然,第七和第八個a,不滿足正則的匹配條件,查詢結束。

我們再延伸一下,剛說的情況的是(?=)放在捕獲的字串後面,它如果放在前面又是什麼結果呢?

例子換成:

(?=hopeful)hope
它的輸出是hope。

正則的意思是:是否能匹配hopeful,如果能,則捕獲hopeful中的hope。當然繼續向後查詢匹配的子串,是從f開始。

比較一下可以看出,(?=hopeful)hope 和 hope(?=ful),兩個正則的效果其實是一樣的。

2、下面說一下 (?<=)

把正則改一下,

(?<=aa)[0-9a-z];
字串還是str = "12332aa438aaf";

它的輸出:43。

這個正則的意思是:匹配這麼乙個字串,它要滿足:是兩位字元(數字或字母),且前面緊跟的是兩個字母 a。

同樣,深入一下,把str換成str = "aaaaaaaa";看一下輸出是什麼,同樣也是:aa aa aa

分析一下:

第一次匹配不用說,是前四個a,輸出的是第三和第四個a;

繼續向後查詢,從第五個a開始,程式發現,第五個和第六個a滿足,因為是兩位字元,且滿足前面緊跟著兩個a(第三和第四個a)。所以匹配成功,輸出第五個和第六個a;

繼續向後查詢,從第七個a開始,程式發現,第七個和第八個a滿足,因為是兩位字元,且滿足前面緊跟著兩個a(第五和第六個a)。所以匹配成功,輸出第七和第八個a。查詢結束。

三、(?!)和(?從外觀上看,和前面一組很相似,區別就是把 『=』 換成了 『!』

那麼意義剛好也是相反的。

[0-9a-z](?!aa)意思是:匹配兩個字元,且後面緊跟著的不是aa

(?用法和前面講的差不多,這裡不再詳述。

JavaScript 正規表示式解惑

正規表示式手冊 我們來舉個例子 電子郵箱 example qq.com 1.username example a z0 9 2.3.公司名 qq.com da z a z 4.匹配開始位置!5.匹配結束位置!6.a za z 代表範圍 7.代表長度 最後,我們對應正則手冊,乙個個對應,就會出現以下正...

正規表示式 常用的正規表示式級正則的捕獲

規則分析 1.可能出現 也可能不出現 2.一位0 9都可以,多位首位不能為0 3.小數部分可能有可能沒有,一旦有後面必須有小數點加數字 let reg d 1 9 d d 數字 字母 下劃線 6 16位 let reg w 1.漢字 u4e00 u9fa5 2.長度 2 10 位 3.可能有譯名 漢...

js 正規表示式捕獲型

測試demo 本文案例位址 分組有四種型別 見案例 捕獲型 非捕獲型 正向前瞻型 反向前瞻型 捕獲性分組 就是捕獲分組所匹配的內容暫且儲存在某個地方,以便下次使用,捕獲性分組以 表示,有些地方將取得捕獲性分組所匹配結果的過程稱之為 反向引用 測試demo中有針對這個的專門案例 非捕獲性分組不捕獲分組...