簡単な正規表現の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オブジェクトには、初期値が0であるlastIndex属性が存在します。

/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を使うかについてはここで説明します。マッチが成功しない時にマッチが完了するまで、マッチが成功しない場合は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には事前調査内容が含まれていません。ここでは多くの判断を簡略化するために使えます。
たとえば、私たちがパスワードを合わせるには、少なくとも1つの大文字と小文字と1つの数字が必要です。長さは少なくとも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ですか?2つの外注内容を理解しています。最後に6つ以上の字母と数字の組み合わせが一致しますが、前は全部事前調査です。lastIndexは常に0ではありません。毎回マッチングは最初からマッチしますので、要求を満足します。
以上は小编が皆さんに绍介した简単な分析正则の表式の中のlastIndexと事前调査で、皆さんに役に立つことを望んでいます。ここでも私たちのサイトを応援してくれてありがとうございます。