NodeJS 使用正则表达式捕获的组作为String替换中的对象键

slsn1g29  于 2023-05-28  发布在  Node.js
关注(0)|答案(1)|浏览(129)

有谁能帮忙解释一下下面代码snipit中显示的行为(来自NodeJS 12控制台)?我正在尝试用捕获组的结果替换字符串的一部分。这实际上是可行的,但是当我使用捕获组结果作为对象中的键时,而不是第一个捕获组,它实际上使用了$1。

> tmp 
{ LOCALAS: 'world' } 
> a 
'let the {{{LOCALAS}}} go around' 

> a.replace(/\{\{\{(.+)\}\}\}/g, "$1"); 
'let the LOCALAS go around' 
> a.replace(/\{\{\{(.+)\}\}\}/g, tmp["LOCALAS"]); 
'let the world go around' 
> a.replace(/\{\{\{(.+)\}\}\}/g, tmp["$1"]); 
'let the undefined go around'

> tmp["$1"] = "NO"; 
'NO' 
> a.replace(/\{\{\{(.+)\}\}\}/g, tmp["$1"]); 
'let the NO go around'

一位朋友给了我一个有效的答案,但我仍然很想知道为什么上面的行为是这样的。

> a.replace(/\{\{\{(.+)\}\}\}/g, function(_,k){return [tmp[k]]});
'let the world go around'
qlckcl4x

qlckcl4x1#

我一直在寻找同样的东西,遇到了这个问题。
在我的例子中,我需要在eval中使用捕获的值,而不是查找。
正如其他人所指出的,我们只能在纯文本替换中使用捕获组。
这是可行的:

str.replace(/\{\{\{(.+?)\}\}\}/g, '$1')

但这不起作用:

str.replace(/\{\{\{(.+?)\}\}\}/g, tmp['$1'])

这是因为tmp['$1']将在调用replace之前进行计算。
因为你知道可用的键,你可以简单地迭代它们并像这样进行替换:

let str = 'this is a {{{adj}}} text used as a {{{adj}}} {{{noun}}}';
const tmp = {
    'adj'  : 'short', 
    'noun' : 'example',
};

Object.keys(tmp).forEach(key => {
    const replaceRegex = new RegExp(`\{\{\{${key}\}\}\}`, 'g');
    str = str.replace( replaceRegex, tmp[key] );
});

console.log(str); // prints: "this is a short text used as a short example"

在我的例子中,值是未知的,所以我通过预先提取值然后迭代它们来解决它:

let str = 'Mario has {{{"Mario".length}}} letters in his name, and Bowser has {{{"Bowser".length}}}';

const expressions = [];
const captureRegex = /\{\{\{(.*?)\}\}\}/g;
const matches = str.matchAll(captureRegex );
for (const match of matches) expressions.push(match[1]);

expressions.forEach(expression => {
    const replaceRegex = new RegExp(`\{\{\{${expression}\}\}\}`, 'g');
    str = str.replace( replaceRegex, eval(expression) );
});

console.log(str); // prints: "Mario has 5 letters in his name, and Bowser has 6"

相关问题