4

RegExp 可以用涉及所谓的标记表达式的替换来替换匹配的模式

例子:

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

这将导致

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

生活很酷,因为somefull匹配,并且替换字符串中的 $1 反映了大括号中匹配的标记表达式,在这种情况下 - 恰好只有somefull

现在,我们有了这个想法——我正在寻找一个想法来做以下事情:

之前的字符串:

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

字符串后

"{timeOfEffect: 259200}"

这些值是这样表示的,因为它们是由人类编辑为可掌握的术语,例如 (60 sec * 60 min * 24 hours)*3 => 3 days (don't ask. Client's request),但用计算机术语读取,例如 259200 in秒,并且可能包含许多该模式的发生。

我想尝试创建一个替换表达式,将 $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返回第一场比赛。在替换语句中处理它之后 - 下一个搜索再次从字符串的开头开始 - 这是一个 60K 长度的字符串......

一个好的解决方案将是以下之一:a)从索引开始执行匹配(不为此创建新的子字符串)b)提供允许评估的替换表达式

另一种方法是对字符串进行标记,并以位为单位处理它——这是一个完全替代RegExp需要大量代码和努力的方法,在这种情况下,我只会忍受性能损失或进行更好的战斗关于这个要求的更好的选择......

帮助任何人?

4

2 回答 2

7
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)
于 2011-03-04T09:56:30.967 回答
5
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}

js小提琴

eval()可以安全使用,因为我们已确保字符串仅包含0-9, , \n, \t, /, *,-+. 我希望可能有类似的东西Math.parse()但没有。

如果您需要需要括号的更复杂的数学,只需将转义(和添加)到正则表达式字符范围。

于 2011-03-04T09:20:44.227 回答