關于JS的正則表達式騷操作

本文是lhyt本人原創(chuàng),希望用通俗易懂的方法來理解一些細節(jié)和難點。轉載時請注明出處。文章最早出現于本人github

0.前言

本文主要介紹了捕獲和非捕獲的概念,并舉了一些例子,這些都是正則表達式在js中進階的一些用法。后面有彩蛋哦

1.捕獲

1.1RegExp對象的相關屬性

一般用()括住的就是捕獲組,而且類似于算術中的括號,從左到右,逐層去括號。比如存在(A)((B)C)這種,他捕獲到的將會是(A)((B)C)、(B)、((B)C),并在內存中存放,可以通過RegExp對象的$屬性來訪問到。

/(1((2)3))/.test('123')

RegExp.$1 //123

RegExp.$2 //2

RegExp.$3 //23

/(((1)2)3)/.test('123')

RegExp.$1 //123

RegExp.$2 //12

RegExp.$3 //1

這個順序,按左括號的順序來算的,第幾個(就表示第幾個$符號屬性,一般從1開始,最多$9

還有一些舊的RegExp長屬性名,在高級程序設計108頁里面

簡寫的話還是有很多不兼容的問題的,最好寫全稱

1.2數字的反向引用

有的人就問,用正則怎么匹配AABB類型的詞語?比如高高興興、亮晶晶這些。在正則里面反斜杠+數字就可以做到,表示重復第n個捕獲組的內容,這個n和上面$后面的數字同理:

/(.)\1(.)\2/.test('高高興興') //TRUE,第一個和第二個相同,第三四個相同

/(.)(.)\2/.test('亮晶晶') // TRUE ,后面兩個相同

2.非捕獲

以 (?) 開頭的組是非捕獲組,它不捕獲文本 ,也不針對組合計進行各種操作,不將匹配到的字符存儲到內存中,從而節(jié)省內存。也就是上面所講的$屬性他都不會具有。一般用于只需要檢測結果的情況。

(?:a)非捕獲一個a

/(?:a)1(?:b)/.test('a1b') //true

RegExp.$1 //''

var reg = /(?:\d{4})-(\d{2})-(\d{2})/

var date = '2018-01-02'

reg.test(date)

RegExp.$1 // 01

RegExp.$2 // 02

2.1斷言

也有人叫前瞻,顧名思義,就是往前面(右邊)看,看看是不是某個東西。

(?=x) 匹配后面是x的數據 :

/i am (?=a)/.test('i am a') //你右邊是a

(?!x) 匹配后面不是x的數據

/i am (?!a)/.test('i am b') //你右邊不是a

2.2篩選

(?!B)[A-Z]:在大寫字母集合中,除去B

/(?!B)[A-Z]/.test('A') //true

/(?!B)[A-Z]/.test('B') //false

3.匹配模式

3.1惰性匹配和貪婪模式

*? 重復0次或更多次

+? 重復一次或更多次

?? 重復0次或一次

{n,}? 重復n次或更多次

{n,m}? 重復n到m次

以上所有的匹配都是盡可能的少重復,只要滿足條件就行了,不繼續(xù)匹配了,在某個程度來說也是性能優(yōu)化的方法之一。

那么貪婪模式就是沒有做了上面的措施的都屬于貪婪模式,比如正則元字符、量詞單獨出現的情況。

對于字符串'abbba'使用/ab*/g和/ab*? /g

貪婪模式:ab* 結果:abbb 和 a,第一次找到了a,繼續(xù)找發(fā)現后面接幾個b也是符合的,直到發(fā)現了第二個a才停止,再找到第二個a

惰性匹配:ab*? 結果:a 和 a,第一次找到了a,*的要求是不需要b也可以,所以停止,接著又找到第二個a

彩蛋:

檢測一個數是否是質數的方法

相信大家都見過一個很強大的函數,一行代碼判斷出一個數是不是質數:

function isPrime(n){

return n<2?false:!/^(11+?)\1+$/.test(Array(n+1).join('1'))

}

看上去好像很牛逼,容我細細道來:

首先最小的質數是2,所以先判斷是否小于2

如果大于2,先創(chuàng)建一個長度是n的字符串,里面鋪滿了1。Array(n+1)創(chuàng)建n+1個空位(undefined),再用1作為分隔符分開轉化為字符串,所以就得到一個長度為n的字符串,全是1組成

^11+?怎么理解

表示以1開頭,后面惰性匹配多個1(1個或者無窮個)

\1+$怎么理解

表示重復^11+?這段匹配到的內容

合起來怎么理解

神奇的地方來了,首先,惰性匹配的是一個1,也就是11,后面重復11的整數次,也就是重復2次4次6次...等等,如果剛剛好匹配到了,說明這個數能被整除,說明他不是質數。如果后面的字符串不能構成2的整數倍個11,那么第一輪惰性匹配失敗。

接著第二輪惰性匹配,匹配11,也就是前面捕獲的是111,那么后面就開始重復111的整數倍,如果剛剛好能匹配完,說明不是質數

接著第三輪,匹配111,捕獲到1111,后面重復1111的整數倍

...

直到不能再匹配,說明這個數就是質數。

其實,里面相當于循環(huán)

for(var i = 2;i<n;i++){

if(n%i==0){return false}

}

return true

正則的強大,真的是法力無邊。jQuery作者正則玩得飛起,號稱世界上最強的選擇器sizzle,就是強大正則做出來的


原文來自lhyt的github

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容