JavaScript 正则表达式有奇怪的行为

JavaScript regular expression having a weird behaviour

我目前正在为我正在维护的 Discord 机器人制作脚本语言,但我遇到了一个奇怪的问题。下面的代码以一个字符串(I think {if:3|=|0|you are|TechRax is} {range:1|100})作为输入,使用字符串的match方法从字符串中获取所有函数(表达式:/\{(.*?):(.*?)\}/g)。然后使用 forEach,我处理所有这些匹配项,然后使用 replace 方法将匹配的内容替换为字符串中的结果。

这是我使用的代码:

let newString = 'I think {if:3|=|0|you are|TechRax is} {range:1|100}';
const functionPattern = /\{(.*?):(.*?)\}/g;
const foundFunctions = newString.match(functionPattern);
if (!foundFunctions) throw new Error('No function found');

foundFunctions.forEach((fn) => {
  const parsedInput = functionPattern.exec(fn); // = null once the second iteration begins... ? only the first one work. Same issue if I invert the function orders (first works, second and + no)
  if (!parsedInput || !parsedInput[1] || !parsedInput[2]) return;

  try {
    /*const customFunction = new (require(`../../Production/Tags/${parsedInput[1]}`))(this.client, context, contextType);
    if (!customFunction) return;

    const result = customFunction.run(parsedInput[2].split('|'));*/
    const result = 'Stack Overflow test';
    newString = newString.replace(fn, result);
  } catch (e) {
    newString = newString.replace(fn, e);
  }
});

// Print newString here (depends if you're on browser or node)

在此上下文中,this.client.constants.functionPattern = /\{(.*?):(.*?)\}/gfoundFunctions = ['{if:4|=|0|you are|alien is}', '{range:1|100}']newString = 'I think {if:{argslen}|=|0|you are|{args} is} {range:1|100}'

现在让我们开始描述行为,第一次迭代进行得很顺利:函数模块被导入,它被处理并且最终内容被替换为字符串。

问题涉及 second 一个(和所有其他),函数表达式 returns nullexec 方法。我根本不明白这一点,首先我认为这是我的 RegExp 的一种错误,也许 {random:1|100} 不匹配但不匹配,因为它在 Regexr.com 上完美运行......最奇怪的是:如果我评估了它 (/\{(.*?):(.*?)\}/g.exec('{range:1|100}),它不是 return null,而是我期望的实际结果。

我想我在某个地方错了,但经过几个小时后我仍然不明白为什么它不工作。 我希望你能帮助我,谢谢! 如果您需要任何补充信息,我就在这里。

问题是您正在定义正则表达式 GLOBAL

  • 但不要在循环内重置内部指针:myRegex.lastIndex = 0;(参见MDN
  • 或者,您可以在 forEach 中重新创建一个正则表达式。

let newString = 'I think {if:3|=|0|you are|TechRax is} {range:1|100}';
let functionPattern = /\{([^}]*):([^}]*)\}/g;
const foundFunctions = newString.match(functionPattern);
if (!foundFunctions)
 throw new Error('No function found');

foundFunctions.forEach(fn => {
  //const functionPattern = /\{([^}]*):([^}]*)\}/g; // or redeclare
  const parsedInput = functionPattern.exec(fn);
  if (!parsedInput || !parsedInput[1] || !parsedInput[2]) return;

  try {
    const result = 'Stack Overflow test';
    newString = newString.replace(fn, result);
    functionPattern.lastIndex = 0;  // reset internal pointer of your regex
  } catch (e) {
    newString = newString.replace(fn, e);
  }
});
console.log(newString);

我差点忘了:我建议使用更强大的正则表达式模式:\{(\[^}\]*):(\[^}\]*)\}
不过,你的模式似乎还不错。