我將 RegExp 物件存盤在一個變數中,并將其用于將字串陣列映射到物件陣列(已決議的電子郵件收件人),但它不起作用,就好像 RegExp 物件無法運行其.exec()方法超過一次。
但是,如果我使用正則運算式文字而不是存盤的物件,它會按預期作業。
我無法理解這種行為背后的原因。這是預期的,還是可能是一個錯誤?
編碼:
const pattern = /^\s*(?<name>\w.*?)?\W (?<address>[a-zA-Z\d._-] @[a-zA-Z\d._-] \.[a-zA-Z\d_-] )\W*$/gi;
const input = "John Doe [email protected]; Ronald Roe <[email protected]>";
const splitValues = input.split(/[\r\n,;] /).map(s => s.trim()).filter(s => !!s);
const matchGroups1 = splitValues.map(s => pattern.exec(s));
console.log('Using pattern RegExp object:', JSON.stringify(matchGroups1, null, 2));
const matchGroups2 = splitValues.map(s => /^\s*(?<name>\w.*?)?\W (?<address>[a-zA-Z\d._-] @[a-zA-Z\d._-] \.[a-zA-Z\d_-] )\W*$/gi.exec(s));
console.log('Using literal regular expression:', JSON.stringify(matchGroups2, null, 2));
輸出:
[LOG]: "Using pattern RegExp object:", "[
[
"John Doe jdoe@acme.com",
"John Doe",
"jdoe@acme.com"
],
null
]"
[LOG]: "Using literal regular expression:", "[
[
"John Doe jdoe@acme.com",
"John Doe",
"jdoe@acme.com"
],
[
"Ronald Roe <rroe@acme.com>",
"Ronald Roe",
"rroe@acme.com"
]
]"
在 TypeScript 操場上進行測驗
uj5u.com熱心網友回復:
不同之處在于/g您傳遞給兩個正則運算式的標志。來自MDN:
RegExp.prototype.exec()帶有g標志的方法迭代地回傳每個匹配項及其位置。const str = 'fee fi fo fum'; const re = /\w \s/g; console.log(re.exec(str)); // ["fee ", index: 0, input: "fee fi fo fum"] console.log(re.exec(str)); // ["fi ", index: 4, input: "fee fi fo fum"] console.log(re.exec(str)); // ["fo ", index: 7, input: "fee fi fo fum"] console.log(re.exec(str)); // null
因此/g,在正則運算式中,正則運算式物件本身變成了一種有趣的可變狀態跟蹤器。當您呼叫正exec則/g運算式時,您正在匹配并在該正則運算式上設定一個引數,該引數會記住它下次停止的位置。這樣做的目的是,如果你匹配同一個字串,你將不會得到相同的匹配兩次,從而允許你使用while類似于在 Perl 中撰寫全域正則運算式匹配的方式來使用回圈進行可變技巧。
但是由于您要匹配兩個不同的字串,因此會導致問題。讓我們看一個簡化的例子。
const re = /a/g;
re.exec("ab"); // Fine, we match against "a"
re.exec("ba"); // We start looking at the second character, so we match the "a" there.
re.exec("ab"); // We start looking at the third character, so we get *no* match.
而在您每次都生成正則運算式的情況下,您永遠不會看到這種狀態,因為正則運算式物件每次都是重新創建的。
/g所以總結是:如果您打算針對多個字串重用正則運算式,請不要使用。
uj5u.com熱心網友回復:
請參閱為什么 Javascript 的 regex.exec() 并不總是回傳相同的值?. 問題是exec有狀態的:換句話說,它在最后一個索引之后開始下一個搜索。pattern.lastIndex = 0;您可以通過包含在: 中來避免該問題,map或者按照您的建議使用文字。
const pattern = /^\s*(?<name>\w.*?)?\W (?<address>[a-zA-Z\d._-] @[a-zA-Z\d._-] \.[a-zA-Z\d_-] )\W*$/gi;
const input = "John Doe [email protected]; Ronald Roe <[email protected]>";
const splitValues = input.split(/[\r\n,;] /).map(s => s.trim()).filter(s => !!s);
const matchGroups1 = splitValues.map(s => {pattern.lastIndex = 0; return pattern.exec(s)});
console.log('Using pattern RegExp object:', JSON.stringify(matchGroups1, null, 2));
const matchGroups2 = splitValues.map(s => /^\s*(?<name>\w.*?)?\W (?<address>[a-zA-Z\d._-] @[a-zA-Z\d._-] \.[a-zA-Z\d_-] )\W*$/gi.exec(s));
console.log('Using literal regular expression:', JSON.stringify(matchGroups2, null, 2));
游樂場鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/459407.html
標籤:javascript 打字稿
