正则表达式优化和最佳实践

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 来做得更好:%([^=]*)=(.*)

最后,如果不允许使用空名称,请将第一个星号替换为加号:%([^=]+)=(.*)

这是一个很好的资源:Regex Tutorial - Repetition with Star and Plus