Оптимизация Regex и лучшие практики - PullRequest
1 голос
/ 10 мая 2019

Мне нужно разобрать информацию из устаревшего интерфейса.У нас нет возможности обновить устаревшее сообщение.Я не очень хорошо разбираюсь в регулярных выражениях, но мне удалось написать такое, которое делает то, что я хочу.Мне просто нужно рецензирование и обратная связь, чтобы убедиться, что это чисто.

Сообщение из прежней системы возвращает значения, аналогичные приведенному ниже примеру.

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

Этот код работает, и я могу добавить частичные совпадения в середине имени /ценности без каких-либо нарушений.Я должен предположить, что любая комбинация символов может появиться в совпадении «значений».То есть в сообщении могут быть знаки равенства и процента.

  • Достаточно ли чисто?
  • Есть ли что-то, что может нарушить выражение?

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

Прежде всего, не экранируйте символы, которые не нужно экранировать: %(.*)=(.*)

Проблема с вашим выражением: знак равенства в значении сломает ваш синтаксический анализатор.%name0=val=ue приведет к name0=val = ue вместо name0 = val=ue.

Одно из возможных исправлений - сделать первое повторение ленивым, добавив знак вопроса: %(.*?)=(.*)

Но это не оптимально из-за ненужного возврата.Вы можете добиться большего успеха, используя отрицательный класс символов: %([^=]*)=(.*)

И, наконец, если пустые имена не допускаются, замените первую звездочку на плюс: %([^=]+)=(.*)

Этохороший ресурс: Regex Tutorial - Повторение со звездами и плюсами

2 голосов
/ 10 мая 2019

Ваше выражение в порядке, и заключить его в две группы захвата просто, чтобы получить желаемые переменные и значения.

Возможно, вам не нужно избегать некоторых символов, и это все равно будет работать.

Вы можете использовать этот инструмент и тестировать / редактировать / изменять / изменять свои выражения, если хотите:

%(.+)=(.+)

Поскольку ваши данные довольно структурированы, вы также можете сделать это с помощью разбиения строки и получить те же желаемые результаты, если хотите.

Описательный график RegEx

Этот график показывает, как будет работать выражение, и вы можете визуализировать другие выражения в этой ссылке :

enter image description here

JavaScript Test

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 показывает производительность этого выражения с использованием простого цикла 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. ? ");
...