RegExp exec - 字符串操作

时间:2015-08-11 12:43:26

标签: javascript regex

我有一个字符串,我试图使用正则表达式操作,如下所示:

var str = 'This is a string with 1: {{param1}}, 2: {{param2}} and 3: {{param3}}',
    reg = /{{.*?}}/ig;

while (field = reg.exec(str)) {
    str = str.replace(field, 'test');
}

{{param2}}永远不会被替换 - 我的猜测是因为我在通过RegExp.exec(...)运行时操纵字符串。但不能肯定。

我尝试了以下内容(因为我注意到RegExp.exec(...)返回一个数组) - 仍然没有运气:

var str = 'This is a string with 1: {{param1}}, 2: {{param2}} and 3: {{param3}}',
    reg = /{{.*?}}/ig;

while (field = reg.exec(str)) {
    str = str.replace(field[0], 'test');
}

有什么想法吗?

编辑:此功能的当前结果是:

'This is a string with 1: test, 2: {{param2}}, test and 3: test'

3 个答案:

答案 0 :(得分:3)

您应该删除g标记。

var str = 'This is a string with 1: {{param1}}, 2: {{param2}} and 3: {{param3}}',
    reg = /{{.*?}}/; 



while (field = reg.exec(str)) {
    str = str.replace(field, 'test');
    console.log(str)
}

结果:

第一次迭代:

  

这是一个包含1:test,2:{{param2}}和3:{{param3}}

的字符串

第二:

  

这是一个包含1:test,2:test和3:{{param3}}

的字符串
第三:

  

这是一个包含1:test,2:test和3:test

的字符串

另一个选择是:

 str = str.replace(/{{.*?}}/g, 'test');

这也将产生:

  

这是一个包含1:test,2:test和3:test

的字符串

修改:

添加到Anonymous的答案:

问题是每个replace - 使原始字符串更短。索引是在开头计算的,原始的较长行。

换句话说,如果您想要将{{param1}}(长度为9)的长度表达式替换为另一个长度为9的字符串,例如:**test1**,那么代码可以工作:

var str = 'This is a string with 1: {{param1}}, 2: {{param2}} and 3: {{param3}}',
    reg = /{{.*?}}/g


while (field = reg.exec(str)) {

    str = str.replace(field, '**test1**');
    console.log(str)
}

结果:

  

This is a string with 1: **test1**, 2: **test1** and 3: **test1**

答案 1 :(得分:1)

我建议通过提供函数来使用String#replace

var text = 'This is a string with 1: {{param1}}, 2: {{param2}} and 3: {{param3}}';

var result = text.replace(/{{.*?}}/g, function (match) {
    // *match* contains the full match, if you have captures
    // then they will be handed in as additional arguments 
    return 'test';
});

在我看来,这比搞乱指数等更清洁。 See this fiddle用于工作版本。

答案 2 :(得分:0)

你是对的。由于更换,它几乎没有错过。以下是正则表达式匹配的执行顺序:

  • 在第一个执行官之后,reg.lastIndex设置为35。
  • 要检查的剩余字符串将变为', 2: {{param2}} and 3: {{param3}}'
  • 第一次替换后,要匹配的剩余字符串变为'{param2}} and 3: {{param3}}',因为lastIndex不会从35更改。
  • 正常表达式匹配的下一次迭代发生,但它与{param2}}不匹配,因此它会保持匹配,直到达到'{{param3}}'

这一切都是因为g lobal正则表达式标志保存了lastIndex。相反,您可以删除全局标记,以便在单个匹配终止后自动将lastIndex设置为0。但是,这确实意味着正则表达式将始终从头开始匹配。更好的选择是将lastIndex设置到您需要的位置。

var str = 'This is a string with 1: {{param1}}, 2: {{param2}} and 3: {{param3}}',
    reg = /{{.*?}}/ig,
    replacement = 'test';

while (field = reg.exec(str)) {
    str = str.replace(field[0], replacement);
    reg.lastIndex = reg.lastIndex - field[0].length + replacement.length;
}
console.log(str);