【问题标题】:Regex optimization and best practice正则表达式优化和最佳实践
【发布时间】:2019-05-10 12:19:16
【问题描述】:

我需要从旧界面解析出信息。我们无法更新旧消息。我对正则表达式不是很精通,但我设法写了一个能做我想做的事。我只需要同行评审和反馈以确保它是干净的。

来自旧系统的消息返回类似于以下示例的值。

%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);
}

此代码有效,我可以在名称/值的中间添加部分匹配而不会破坏任何内容。我必须假设任何字符组合都可能出现在“值”匹配中。这意味着它可以在消息中包含等号和百分号。

  • 这够干净吗?
  • 有什么东西会破坏表达式吗?

【问题讨论】:

  • 如果您的代码运行良好并且没有问题,请考虑将问题发布到Code Review

标签: javascript regex regex-lookarounds regex-group regex-greedy


【解决方案1】:

首先不要转义不需要转义的字符:%(.*)=(.*)

您的表达式的问题:值中的等号会破坏您的解析器。 %name0=val=ue 将导致 name0=val=ue 而不是 name0=val=ue

一种可能的解决方法是通过附加问号使第一次重复变得懒惰:%(.*?)=(.*)

但由于不需要回溯,这不是最佳选择。使用否定字符类可以做得更好:%([^=]*)=(.*)

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

这是一个很好的资源:@​​987654321@

【讨论】:

  • 感谢您的反馈和教程。
【解决方案2】:

你的表达式很好,用两个捕获组包装它很容易得到你想要的变量和值。

您可能不需要转义一些字符,它仍然可以工作。

您可以使用this tool 并根据需要测试/编辑/修改/更改您的表达式:

%(.+)=(.+)

由于您的数据非常结构化,如果您愿意,您也可以通过字符串拆分来执行此操作并获得相同的所需输出。

正则表达式描述图

此图表显示了表达式的工作原理,您可以在此 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 sn-p 使用简单的 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: $1 \n Group #2: $2 \n Group #3: $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. ? ");

【讨论】:

  • 感谢您的反馈和测试工具链接。
猜你喜欢
  • 2013-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-14
  • 2015-04-06
  • 2020-11-07
  • 1970-01-01
相关资源
最近更新 更多