我有一個包含合并欄位的模板字串:
例子:
let templateStr = '[!field]: value entered is too large. (max length=[!limit])';
我有一個遵循上述模板格式的錯誤訊息字串,這里的欄位名稱和最大長度可以根據用戶嘗試保存的欄位而有所不同。
例子:
let errorMessage = 'Country: value entered is too large. (max length=80)';
在這里,我試圖根據errorMessage提取templateStr中參考的變數(欄位、限制) 。
extractTemplateVar(errorMessage, templateStr) // should return field='Country' and limit='80'
如果errorMessage = 'Email: value entered is too large. (max length=100);
那時,
extractTemplateVar(errorMessage, templateStr) // should return field='Email' and limit='100'
我嘗試使用正則運算式,根據模板從字串中匹配和提取變數。它沒有按預期作業
let pattern = '(. ): data value too large: .*(max length=(. ))';
new RegExp(pattern ).exec(errorMessage);
各位大俠,請幫我解決這個問題。提前謝謝各位。
uj5u.com熱心網友回復:
這有點惡心。可能有更好的方法。
第 1 部分,從模板中提取變數名稱。
第 2 部分,按這些名稱拆分模板以獲得“模板的其余部分”
第 3 部分,將“模板的其余部分”片段轉換為正則運算式兼容格式。我可能錯過了一些需要逃避的事情
第 4 部分,將模板片段連接回與正則運算式兼容的字串,由 (.*?) 分隔 - 這將捕獲變數的實際值
第 5 部分,針對訊息運行構造的正則運算式,以提取變數值
第 6 部分,從變數名稱和值生成回傳結構
let templateStr = '[!field]: value entered is too large. (max length=[!limit])';
let errorMessage = 'Country: value entered is too large. (max length=80)';
const extractTemplateVars = (template, message) => {
let regex = /\[\!(.*?)\]/g;
let splitRegex = /\[\!.*?\]/g;
let match, matches = [];
// Part 1
while (match = regex.exec(template)) {
matches.push(match[1]);
}
// Part 2
let arr = template.split(splitRegex);
// Part 3
arr = arr.map(s =>
s.replaceAll("\\", "\\\\")
.replaceAll("(", "\\(")
.replaceAll(")", "\\)")
.replaceAll(".", "\\.")
);
// Part 4
let reStr = arr.join("(.*?)");
let re = new RegExp(reStr, "g");
// Part 5
let m = re.exec(message);
let [garbage, ...values] = m;
// Part 6
let output = matches.map((match, i) => ({[match]: values[i]}));
console.log(output);
};
extractTemplateVars(templateStr, errorMessage);
uj5u.com熱心網友回復:
根據您的示例字串,作為一種模式,您可以使用 2 個捕獲組:
([^:\n] ):.*?\(max length=([^\s=()] )\)
模式匹配:
([^:] )捕獲組 1,匹配除 a:或換行符之外的任何字符 1 次以上:.*?匹配:和其余行不貪心\(max length=匹配(max length=([^\s=()] )捕獲組 2,匹配 1 次以上的任何字符,除了=()
\)匹配)
正則運算式演示
const regex = /([^:\n] ):.*?\(max length=([^\s=()] )\)/;
const errorMessage = 'Email: value entered is too large. (max length=100)';
const m = errorMessage.match(regex);
if (m) {
console.log(`field='${m[1]}' and limit='${m[2]}'`);
}
如果您只想匹配限制的數字,您也可以使用\d
([^:\n] ):.*?\(max length=(\d )\)
uj5u.com熱心網友回復:
這確實是一項新穎的任務。以下是我為解決此問題而采取的步驟:
- 使用正則運算式提取模板 (
[!TEMPLATE_NAME]) - 在模板字串中,獲取模板前后的所有文本,稍后用于正則運算式外觀
- 創建具有動態環視的正則運算式。請注意,我們轉義了常規文本以避免正則運算式中的奇怪行為
- 匹配給定字串中的文本并使用它
- $$$ 利潤!$$$
這是你的代碼:
let templateStr = '[!field]: value entered is too large. (max length=[!limit])';
let errorMessage = 'Country: value entered is too large. (max length=80)';
function extractTemplateVar(str, template) {
const match = /\[!. ?\]/g,
data = [],
result = {},
escapeRegex = str => str.replace(/[-\/\\^$* ?.()|[\]{}]/g, "\\$&");
let matching;
while(matching = match.exec(template)) {
// go through everything that looks like a template and get the text before and after it
const index = matching.index;
const str = matching[0];
const text = str.match(/(?<=\[!). ?(?=\])/)[0]; // extract the exact text from the template
const endIndex = str.length index;
const front = escapeRegex(template.substr(0, index).replace(/\[!. ?\]/g, "::TMP::")); // text before
const back = escapeRegex(template.substr(endIndex).replace(/\[!. ?\]/g, "::TMP::")); // text after
data.push({ text, back, front });
}
data.forEach(n => {
const re = new RegExp(`(?<=${n.front.replaceAll("::TMP::", ".*?")}). ?(?=${n.back.replaceAll("::TMP::", ".*?")})`); // create regex with dynamic lookaround
const findText = str.match(re)[0];
result[n.text] = findText;
});
return result;
}
console.log(extractTemplateVar(errorMessage, templateStr));
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/443795.html
標籤:javascript 正则表达式 细绳
下一篇:查找字串中的第一個字母
