JavaScript, RegExp - заменить оцененным выражением, включающим теговые выражения? - PullRequest
4 голосов
/ 04 марта 2011

RegExp может заменить сопоставленные шаблоны заменами, включающими так называемые помеченные выражения

Пример:

var s = "... some string with full things...";
s = s.replace(/(some|full)/gi, "\"aw$1\");

, что приведет к

'... "awsome" string with "awfull" things...'

И жизнь классная, потому что некоторые и full совпадают, и $ 1 в замененной строке отражает совпадение Tagged Expression в фигурных скобках, в этом регистр - точно только некоторые или полные .

Теперь, когда у нас появилась идея - Я ищу идею сделать следующее:

Строка перед:

"{timeOfEffect: 3*24*60*60 }"

Строка после

"{timeOfEffect: 259200}"

Значения представлены так, потому что они редактируются людьми в понятные термины, такие как (60 сек * 60 мин * 24 часа) * 3 => 3 дня (не спрашивайте. Запрос клиента), но читайте в компьютерных терминах как 259200 в секундах, и может содержать много повторений этого паттерна.

Я думал о том, чтобы попытаться создать выражение замены, которое умножает 1 и 2 доллара, или даже передать 1 и 2 доллара функции или передать 1 * 2 $ в контекст оценки, но мне нужно создать для него функцию и сделать это вручную.

Самое близкое, что у меня есть

var x = /([0-9]*)\s\*\s([0-9]*)/g
  , r = function(m){
           return m[1] * m[2];
        }
while (m = x.exec(s))
  s = s.replace( x, r(m));

Это немного отстой, потому что exec возвращает только первое совпадение . После обработки в операторе замены следующий поиск начинается снова с начала строки, которая представляет собой строку длиной 60 КБ ...

Хорошим решением будет одно из следующих: а) выполнить сопоставление, начиная с индекса (без создания для этого новой подстроки) б) предоставить выражение замены, которое позволяет оценку

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

Помогите кому-нибудь?

Ответы [ 2 ]

7 голосов
/ 04 марта 2011
var s = "timeOfEffect: 3*24*60*60 var: 6*8 ";
var r = new RegExp("([0-9*+-/]{0,}[0-9])","g");
s = s.replace(r,function(match){ return eval(match); });
alert(s)
5 голосов
/ 04 марта 2011
var str = '{timeOfEffect: 3*24*60*60}, {timeOfEffect: 1+7}, {timeOfEffect: 20-3}, {timeOfEffect: 3 / 0}';

var result = str.replace(/\s([\d\/\*\-\+\s]+?)\}/g, function(all, match) {
    return eval(match) + '}';
});

document.body.innerHTML = result;
// {timeOfEffect:259200}, {timeOfEffect:8}, {timeOfEffect:17}, {timeOfEffect:Infinity}

jsFiddle .

eval() безопасно использовать, поскольку мы убедились, что строка содержит только 0-9, , \n, \t, /, *, - и +. Я был в надежде может быть что-то вроде Math.parse(), но это не так.

Если вам нужна более сложная математика, требующая скобок, просто добавьте экранированные ( и ) в диапазон символов регулярного выражения.

...