JavaScript:查找与 .exec() 的连续匹配
JavaScript: Finding successive matches with .exec()
我有一个具有无数属性的对象,例如描述产品的颜色和品牌。我正在寻找一种以段落形式动态生成产品描述的方法(因为 API 没有提供),我想出了一种方法,方法是编写 "templates" 具有 "props" 括在方括号 {{}}
中。我通过将 "props" 替换为键的值来在字符串中注入对象属性,从而为 "parse" 模板编写了一个函数。
例如:
对象:{color: 'white'}
模板:"The bowl is {{color}}."
结果:"The bowl is white."
出于某种原因,我的解析功能无法正常工作。 {{general_description}}
未解析。
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/g;
const parse = (template) => {
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
template = template.replace(match, obj[key]);
}
return template;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
我遵循了 MDN docs under Examples > Finding successive matches. It says that I need to first store the regular expression in a variable (e.g., templatePropRe
), for the expression cannot be in the while loop condition or it will loop indefinitely. However, if I do that, my problem is resolved. See here 中提供的示例...没有损坏。
我使用 String.prototype.match, and it works as expected, but I don't have access to the capture so I need to first strip off the brackets using stripBrackets
. See the working example using match
here 重写了函数。
我想知道的是为什么我的parse()
利用RegExp.prototype.exec
的函数不能正常工作?
从正则表达式中删除 /g
标记。根据 documentation,当此标志存在时,它会更新正则表达式对象的 lastIndex
属性,这指示下一次调用 exec()
将从哪里开始搜索匹配项。
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/;
const parse = (template) => {
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
template = template.replace(match, obj[key]);
}
return template;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
发生这种情况是因为您在代码中修改并检查了相同的字符串。
而 regExp 会在每次执行后保存匹配子字符串的索引,而您会更改字符串的长度,而下一次执行的 regEx 会从您预期之外的其他点开始。
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/g;
const parse = (template) => {
var resultStr = template;
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
resultStr = resultStr.replace(match, obj[key]);
}
return resultStr;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
而不是执行两步替换(找到一个匹配项,然后用所需的值替换第一个匹配项)(这很容易出现问题,例如将新字符串传递给同一个 RegExp 时遇到的问题旧的,已经无效的索引),你可以使用 callback method as a replacement argument inside a String#replace
method。这样,结果字符串将在每次匹配时即时构建,从而使代码执行得更快。
查看下面的修复示例:
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const parse = (template) => {
return template.replace(/{{(\w*)}}/g, ([=10=], ) => obj[] ? obj[] : [=10=] );
// ES5 way:
// return template.replace(/{{(\w*)}}/g, function([=10=], ) {
// return obj[] ? obj[] : [=10=];
// });
}
console.log(parse('{{keep}} This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
请注意,此处找到匹配项后,([=12=], ) => obj[] ? obj[] : [=12=]
代码执行以下操作:整个匹配项分配给 [=13=]
变量,第 1 组值分配给 </code> ;然后,如果 <code>obj
中有一个名称为 </code> 的键,则该值将代替匹配项放入结果字符串中的正确位置。否则,整个匹配项将被放回原处(如果要删除键名不存在的 <code>{{...}}
,请替换为 ''
)。
我有一个具有无数属性的对象,例如描述产品的颜色和品牌。我正在寻找一种以段落形式动态生成产品描述的方法(因为 API 没有提供),我想出了一种方法,方法是编写 "templates" 具有 "props" 括在方括号 {{}}
中。我通过将 "props" 替换为键的值来在字符串中注入对象属性,从而为 "parse" 模板编写了一个函数。
例如:
对象:{color: 'white'}
模板:"The bowl is {{color}}."
结果:"The bowl is white."
出于某种原因,我的解析功能无法正常工作。 {{general_description}}
未解析。
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/g;
const parse = (template) => {
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
template = template.replace(match, obj[key]);
}
return template;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
我遵循了 MDN docs under Examples > Finding successive matches. It says that I need to first store the regular expression in a variable (e.g., templatePropRe
), for the expression cannot be in the while loop condition or it will loop indefinitely. However, if I do that, my problem is resolved. See here 中提供的示例...没有损坏。
我使用 String.prototype.match, and it works as expected, but I don't have access to the capture so I need to first strip off the brackets using stripBrackets
. See the working example using match
here 重写了函数。
我想知道的是为什么我的parse()
利用RegExp.prototype.exec
的函数不能正常工作?
从正则表达式中删除 /g
标记。根据 documentation,当此标志存在时,它会更新正则表达式对象的 lastIndex
属性,这指示下一次调用 exec()
将从哪里开始搜索匹配项。
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/;
const parse = (template) => {
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
template = template.replace(match, obj[key]);
}
return template;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
发生这种情况是因为您在代码中修改并检查了相同的字符串。 而 regExp 会在每次执行后保存匹配子字符串的索引,而您会更改字符串的长度,而下一次执行的 regEx 会从您预期之外的其他点开始。
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const templatePropRe = /{{(\w*)}}/g;
const parse = (template) => {
var resultStr = template;
while ((result = templatePropRe.exec(template)) !== null) {
let match = result[0],
key = result[1];
resultStr = resultStr.replace(match, obj[key]);
}
return resultStr;
}
console.log(parse('This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
而不是执行两步替换(找到一个匹配项,然后用所需的值替换第一个匹配项)(这很容易出现问题,例如将新字符串传递给同一个 RegExp 时遇到的问题旧的,已经无效的索引),你可以使用 callback method as a replacement argument inside a String#replace
method。这样,结果字符串将在每次匹配时即时构建,从而使代码执行得更快。
查看下面的修复示例:
var obj = {
brand: "Oneida",
general_description: "Plate",
material: "China",
color: "Bone White",
product_width: "5\""
};
const parse = (template) => {
return template.replace(/{{(\w*)}}/g, ([=10=], ) => obj[] ? obj[] : [=10=] );
// ES5 way:
// return template.replace(/{{(\w*)}}/g, function([=10=], ) {
// return obj[] ? obj[] : [=10=];
// });
}
console.log(parse('{{keep}} This {{color}}, {{material}} {{general_description}} supplied by {{brand}} has a width of {{product_width}}.'));
请注意,此处找到匹配项后,([=12=], ) => obj[] ? obj[] : [=12=]
代码执行以下操作:整个匹配项分配给 [=13=]
变量,第 1 组值分配给 </code> ;然后,如果 <code>obj
中有一个名称为 </code> 的键,则该值将代替匹配项放入结果字符串中的正确位置。否则,整个匹配项将被放回原处(如果要删除键名不存在的 <code>{{...}}
,请替换为 ''
)。