正则表达式优化和最佳实践
Regex optimization and best practice
我需要从旧界面解析信息。我们无法更新遗留消息。我不是很精通正则表达式,但我设法写了一个可以做我想做的事情。我只需要同行评审和反馈来确保它是干净的。
来自遗留系统的消息 returns 值类似于下面的示例。
%name0=value
%name1=value
%name2=value
Expression: /\%(.*)\=(.*)/g;
var strBody = body_text.toString();
var myRegexp = /\%(.*)\=(.*)/g;
var match = myRegexp.exec(strBody);
var objPair = {};
while (match != null) {
if (match[1]) {
objPair[match[1].toLowerCase()] = match[2];
}
match = myRegexp.exec(strBody);
}
此代码有效,我可以在 name/values 的中间添加部分匹配项而不会中断任何内容。我必须假设任何字符组合都可能出现在 "values" 匹配项中。这意味着它可以在消息中包含等号和百分号。
- 这样够干净吗?
- 有什么东西可以破坏表达式吗?
你的表达式很好,用两个捕获组包裹它很容易得到你想要的变量和值。
您可能不需要转义某些字符,它仍然可以工作。
如果您愿意,可以使用 this tool 和 test/edit/modify/change 表达式:
%(.+)=(.+)
由于您的数据非常结构化,如果需要,您也可以使用字符串拆分来执行此操作并获得相同的所需输出。
正则表达式描述图
此图显示了表达式的工作原理,您可以在此 link 中可视化其他表达式:
JavaScript 测试
const regex = /%(.+)=(.+)/gm;
const str = `%name0=value
%name1=value
%name2=value`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
性能测试
此 JavaScript 片段显示了使用简单的 100 万次 for
循环时该表达式的性能。
const repeat = 1000000;
const start = Date.now();
for (var i = repeat; i >= 0; i--) {
const string = '%name0=value';
const regex = /(%(.+)=(.+))/gm;
var match = string.replace(regex, "\nGroup #1: \n Group #2: \n Group #3: \n");
}
const end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test. ");
首先,不需要转义的字符不要转义:%(.*)=(.*)
您的表达式存在问题:值中的等号会破坏您的解析器。 %name0=val=ue
会导致 name0=val
=ue
而不是 name0
=val=ue
.
一个可能的解决方法是通过附加问号使第一次重复变得懒惰:%(.*?)=(.*)
但是由于不需要的回溯,这不是最优的。您可以使用否定字符 class 来做得更好:%([^=]*)=(.*)
最后,如果不允许使用空名称,请将第一个星号替换为加号:%([^=]+)=(.*)
我需要从旧界面解析信息。我们无法更新遗留消息。我不是很精通正则表达式,但我设法写了一个可以做我想做的事情。我只需要同行评审和反馈来确保它是干净的。
来自遗留系统的消息 returns 值类似于下面的示例。
%name0=value
%name1=value
%name2=value
Expression: /\%(.*)\=(.*)/g;
var strBody = body_text.toString();
var myRegexp = /\%(.*)\=(.*)/g;
var match = myRegexp.exec(strBody);
var objPair = {};
while (match != null) {
if (match[1]) {
objPair[match[1].toLowerCase()] = match[2];
}
match = myRegexp.exec(strBody);
}
此代码有效,我可以在 name/values 的中间添加部分匹配项而不会中断任何内容。我必须假设任何字符组合都可能出现在 "values" 匹配项中。这意味着它可以在消息中包含等号和百分号。
- 这样够干净吗?
- 有什么东西可以破坏表达式吗?
你的表达式很好,用两个捕获组包裹它很容易得到你想要的变量和值。
您可能不需要转义某些字符,它仍然可以工作。
如果您愿意,可以使用 this tool 和 test/edit/modify/change 表达式:
%(.+)=(.+)
由于您的数据非常结构化,如果需要,您也可以使用字符串拆分来执行此操作并获得相同的所需输出。
正则表达式描述图
此图显示了表达式的工作原理,您可以在此 link 中可视化其他表达式:
JavaScript 测试
const regex = /%(.+)=(.+)/gm;
const str = `%name0=value
%name1=value
%name2=value`;
let m;
while ((m = regex.exec(str)) !== null) {
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
// The result can be accessed through the `m`-variable.
m.forEach((match, groupIndex) => {
console.log(`Found match, group ${groupIndex}: ${match}`);
});
}
性能测试
此 JavaScript 片段显示了使用简单的 100 万次 for
循环时该表达式的性能。
const repeat = 1000000;
const start = Date.now();
for (var i = repeat; i >= 0; i--) {
const string = '%name0=value';
const regex = /(%(.+)=(.+))/gm;
var match = string.replace(regex, "\nGroup #1: \n Group #2: \n Group #3: \n");
}
const end = Date.now() - start;
console.log("YAAAY! \"" + match + "\" is a match ");
console.log(end / 1000 + " is the runtime of " + repeat + " times benchmark test. ");
首先,不需要转义的字符不要转义:%(.*)=(.*)
您的表达式存在问题:值中的等号会破坏您的解析器。 %name0=val=ue
会导致 name0=val
=ue
而不是 name0
=val=ue
.
一个可能的解决方法是通过附加问号使第一次重复变得懒惰:%(.*?)=(.*)
但是由于不需要的回溯,这不是最优的。您可以使用否定字符 class 来做得更好:%([^=]*)=(.*)
最后,如果不允许使用空名称,请将第一个星号替换为加号:%([^=]+)=(.*)