Discord机器人内联函数嵌套场景的正则匹配需求
解决嵌套内联函数的正则匹配问题
普通正则无法处理嵌套的{...}结构,核心原因是[^\}]会匹配到第一个}就终止,无法识别多层嵌套的括号层级。要支持嵌套场景,需要用递归正则或手动括号计数的方式来匹配成对的括号。
正则方案(支持ES2018+环境)
针对单个函数名,构造能识别嵌套结构的正则:
const createNestedFuncRegex = (funcName) => { // 递归匹配嵌套的{...},捕获函数名后到闭合}前的内容 return new RegExp(`\\{${funcName}((?:[^\\{\\}]|\\{(?R)\\})*)\\}`, 'g'); };
正则解析:
\{${funcName}:精准匹配以{+目标函数名开头的片段((?:[^{}]|\{(?R)\})*):捕获组,匹配函数名后到对应}之间的内容:[^{}]:匹配非括号的任意字符\{(?R)\}:递归调用整个正则,匹配嵌套的{...}结构
\}:匹配与开头{对应的闭合括号
完整替换逻辑示例
要实现完整的嵌套函数替换,必须递归处理参数中的嵌套函数:
// 定义内联函数的处理逻辑 const inlineFunctions = { ping: () => '91', id: (args) => { const processedArgs = args.trim(); return processedArgs === 'author' ? '123456789' : processedArgs; } }; function resolveInlineFunctions(inputStr) { for (const [funcName, handler] of Object.entries(inlineFunctions)) { const regex = createNestedFuncRegex(funcName); inputStr = inputStr.replace(regex, (fullMatch, args) => { // 先递归解析参数里的嵌套函数 const resolvedArgs = resolveInlineFunctions(args); return handler(resolvedArgs); }); } return inputStr; } // 测试 const testInput = '当前延迟:{ping},发送者ID:{id {author}}'; console.log(resolveInlineFunctions(testInput)); // 输出:当前延迟:91,发送者ID:123456789
兼容性备选方案(不支持递归正则时)
如果运行环境不支持ES2018递归正则,可以手动通过计数括号的方式解析:
function findMatchingBracket(str, startIndex) { let count = 1; for (let i = startIndex + 1; i < str.length; i++) { if (str[i] === '{') count++; if (str[i] === '}') count--; if (count === 0) return i; } return -1; // 无匹配括号,处理错误 } function resolveInlineFunctionsFallback(inputStr) { for (const [funcName] of Object.entries(inlineFunctions)) { const funcPrefix = `{${funcName}`; let index = inputStr.indexOf(funcPrefix); while (index !== -1) { const start = index + funcPrefix.length; const end = findMatchingBracket(inputStr, index); if (end === -1) break; const args = inputStr.slice(start, end); const resolvedArgs = resolveInlineFunctionsFallback(args); const result = inlineFunctions[funcName](resolvedArgs); inputStr = inputStr.slice(0, index) + result + inputStr.slice(end + 1); index = inputStr.indexOf(funcPrefix); } } return inputStr; }
注意事项
- 函数名不能包含
{或},需提前约束命名规则 - 替换时必须递归处理参数,才能解析多层嵌套结构
- 手动计数括号的方式兼容性更好,但性能略低于正则方案
内容的提问来源于stack exchange,提问作者disitific
相关产品推荐
相关产品推荐

