首頁  >  文章  >  web前端  >  正規中的lastIndex使用詳解

正規中的lastIndex使用詳解

php中世界最好的语言
php中世界最好的语言原創
2018-03-29 16:20:122088瀏覽

這次帶給大家正規中的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中文網其它相關文章!

推薦閱讀:

使用正規多行模式與單行模式的圖文詳解

基於PHP正規零寬斷言的使用詳解

#

以上是正規中的lastIndex使用詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn