這次帶給大家正規中的lastIndex使用詳解,正規中lastIndex所使用的注意事項有哪些,以下是實戰案例,一起來看一下。
依序寫出下列輸出內容。
var reg1 = /a/; var reg2 = /a/g; console.log(reg1.test('abcabc')); // true console.log(reg1.test('abcabc')); // true console.log(reg1.test('abcabc')); // true console.log(reg1.test('abcabc')); // true console.log(reg2.test('abcabc')); // true console.log(reg2.test('abcabc')); // true console.log(reg2.test('abcabc')); // false console.log(reg2.test('abcabc')); // true
很簡單的一個正規表示式測試,查找字串abcabc中是否有字元a。但是結果卻有一個特殊false存在,Why?
lastIndex(針對於帶參數g的正規表示式)
在每個實例化的RegExp物件中,都存在一個lastIndex屬性,其初始值為0。
/a/.lastIndex // 0 new RegExp('a').lastIndex // 0 lastIndex表示匹配成功时候,匹配内容最后一个字符所在原字符串中的位置 + 1,也就是匹配内容的下一个字符的index(如果匹配内容在字符串的结尾,同样返回原字符串中的位置 + 1,也就是字符串的length)。如果未带参数g,lastIndex始终为0。 var reg = /ab/g; reg.test('123abc'); console.log(reg.lastIndex) // 5 // 匹配内容在最后 var reg = /ab/g; reg.test('123ab'); console.log(reg.lastIndex) // 5 // 不带参数g var reg = /ab/; reg.test('123abc'); console.log(reg.lastIndex) // 0
而這個lastIndex也就是用該正則進行其他匹配操作的時候匹配開始的位置。而匹配失敗時重置lastIndex為0。
var reg = /ab/g; // 初始值为0,从最开始匹配 匹配成功, lastIndex为4 console.log(reg.test('12ab34ab'), reg.lastIndex); // true 4 // 从第4位字符"3"开始匹配 匹配内容为第二个ab lastIndex 为 8 console.log(reg.test('12ab34ab'), reg.lastIndex); // true 8 // 从第8位 (字符长度为8,没有第8位) 开始匹配 匹配不成功 重置lastIndex 为 0 console.log(reg.test('12ab34ab'), reg.lastIndex); // false 0 // 从头匹配 同第一步 console.log(reg.test('12ab34ab'), reg.lastIndex); // true 4
看到這裡題目也就解答完畢,接下來是擴充。
對於未重新宣告的reg容易犯錯的地方。
// 测试字符串str1 和 str2 是否都含有ab字符 var reg = /ab/g; var str1 = '123ab'; var str2 = 'ab123'; console.log(reg.test(str1)); // true console.log(reg.test(str2)); // false
很明顯這裡因為lastIndex的原因導致判斷錯誤。這裡可以修改reg不帶參數g或則重新宣告reg,當然也可以在第一次配對後手動修改reg.lastIndex = 0。
預查
接著說預查,字面上就是預備匹配查詢,也就是查詢匹配內容接下來的內容,但只是預備查詢匹配,並不返回。
經常我們需要匹配到字串中某些字符後面跟某些字符,但是我們不需要匹配結果中包含後面跟的字符,例如:
找出下面字符串中字元後面是2的所有字元。
var str = 'a1b2c22d31e4fg6h2'; 'a1b2c22d31e4fg6h2'.match(/[a-z]2/g); // ["b2", "c2", "h2"]
這樣,雖然能匹配出字串帶2的,但是數字2我們並不需要,這裡只需要字元。而用預查:
'a1b2c22d31e4fg6h2'.match(/[a-z](?=2)/g); // ["b", "c", "h"]
可以看到完全滿足條件,但預查和本文的主題lastIndex又有幾毛錢的關係呢?
我們用test來看看,至於為什麼用test這裡要說明一下,match是匹配所有,直到匹配不成功的時候結束匹配,而匹配不成功時,lastIndex就被重置為0了。
而exec和test是第一次匹配成功或匹配失敗就返回,並不會接著往下匹配。
var reg1 = /[a-z](?=2)/g; var reg2 = /[a-z]2/g; var str = 'a1b2c22d31e4fg6h2'; console.log(reg1.test(str), reg1.lastIndex); // true 3 console.log(reg1.test(str), reg1.lastIndex); // true 5 console.log(reg1.test(str), reg1.lastIndex); // true 16 console.log(reg1.test(str), reg1.lastIndex); // false 0 console.log(reg2.test(str), reg2.lastIndex); // true 4 console.log(reg2.test(str), reg2.lastIndex); // true 6 console.log(reg2.test(str), reg2.lastIndex); // true 17 console.log(reg2.test(str), reg2.lastIndex); // false 0
看出問題沒有?預查的lastIndex不包含預查內容! 這裡就可以用來簡化很多判斷了。
例如我們要匹配密碼必須有至少一個大寫字母,一個小寫字母,一個數字,並且長度至少6位而且只能是數字字母組合。
按照不會預查的情況會這樣去判斷:
/[a-z]/.test(pwd) && /[A-Z]/.test(pwd) && /\d/.test(pwd) && /^[a-zA-Z0-9]{6,}$/.test(pwd);
但是:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z0-9]{6,}$/.test(pwd)
分解出來看:
(?=.*[ a-z]) 是否有小寫字母但是是預查匹配失敗返回false 成功lastIndex不變動,還是為0,同理理解兩外預查內容,最後就是6餵以上的字母數字組合匹配,但是前面都是預查,lastIndex始終未0,每次符合都是從最開始匹配的,所以滿足要求。
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!
推薦閱讀:
#以上是正規中的lastIndex使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!