JavaScript、RegExp - 替换为涉及标记表达式的评估表达式?

发布于 2024-10-20 06:43:38 字数 1346 浏览 1 评论 0原文

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

示例:

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

这将导致

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

生活很酷,因为 somefull被匹配,替换字符串中的 $1 反映了大括号中匹配的标记表达式,在本例中 - 恰好只有 somefull

现在,我们有了这个想法—— 我正在寻找执行以下操作的想法:

String before:

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

String after

"{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 返回仅第一个匹配。 在替换语句中处理它之后 - 下一个搜索再次从字符串的开头开始 - 这是一个 60K 长度的字符串......

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

另一种方法是对字符串进行标记,并以位的形式对其进行处理——这是 RegExp 的完全替代方案,需要大量的代码和工作,在这种情况下,我将忍受性能损失,或者更好地争取更好的替代方案来满足此要求......

帮助任何人吗?

RegExp can replace matched patterns with replacements involving what is known as Tagged Expressions

Example:

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

which will result in

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

And life are cool, because some and full are matched, and $1 in the replaced string reflects the matched Tagged Expression in the braces, in this case - exactly only some or full.

Now, that we got the idea -
I'm looking for an idea to do the following:

String before:

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

String after

"{timeOfEffect: 259200}"

The values are represented like that because they are edited by humans to graspable terms like (60 sec * 60 min * 24 hours)*3 => 3 days (don't ask. Client's request), but read in computer terms like 259200 in seconds, and could contain many occuring of that pattern.

I was thinking to try to create a replacement expression that multiplies $1 and $2, or even pass $1 and $2 to a function, or pass $1 * $2 to an evaluation context, but I have to create a function for it and do it manually.

The closest I got is

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

That sucks a little because exec returns only the first match.
After handling it in the replace statement - next search starts again from the start of the string - which is a string of 60K length...

A good solution will be one of the following:
a) perform the match starting from an index (without creating a new substring for that)
b) provide a replace expression that allows evaluation

The alternative approach will be to tokenize the string, and process it in bits - which is a total alternative to the RegExp that will take a lot of code and effort, in which case I'll just live with the performance penalty or give a better fight on a better alternative for this requirement...

Help anybody?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

当梦初醒 2024-10-27 06:43:38
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)
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)
自找没趣 2024-10-27 06:43:38
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(),但没有。

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

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() is safe to use because we have ensured the string only contains 0-9, , \n, \t, /, *, - and +. I was hoping there may be something like Math.parse(), but there isn't.

If you need more complex math that requires parenthesis, simply add escaped ( and ) to the regex character range.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文