如何匹配{0}并支持转义?修复JS模板转义大括号替换问题
修复.NET风格string.format的转义大括号及错误处理问题
问题分析
你的原代码仅处理了有效占位符的替换,但未实现转义大括号({{→{、}}→})的转换逻辑,同时缺少对无效语法(单独闭合大括号、非数字占位符)的错误检查,导致部分用例无法正常工作。
修复后的完整代码
function format(template: string, ...values: unknown[]): string { // 检查未转义的单独闭合大括号 const unescapedClosingBraceRegex = /(?<!{)}(?!})/g; if (unescapedClosingBraceRegex.test(template)) { throw new Error("Invalid closing brace }"); } // 检查包含非数字的无效占位符 const invalidPlaceholderRegex = /{([^}\d]+)}/g; const invalidMatch = invalidPlaceholderRegex.exec(template); if (invalidMatch) { throw new Error(`Invalid placeholder {${invalidMatch[1]}}`); } // 统一处理转义大括号和有效占位符 return template.replace(/({{)|(}})|{(\d+)}/g, (match, doubleLeft, doubleRight, indexStr) => { if (doubleLeft) { // 转义左大括号:{{ → { return '{'; } if (doubleRight) { // 转义右大括号:}} → } return '}'; } // 处理有效数字占位符 const index = parseInt(indexStr, 10); if (index >= values.length) { throw new Error("Not enough arguments"); } return String(values[index]); }); } // 测试用例验证 console.log([ format("{0}", 42), // 输出 "42" format("{0} {1}", 42, "bar"), // 输出 "42 bar" format("{1} {1}", 42, "bar"), // 输出 "bar bar" format("{{0", 42), // 输出 "{0" format("{{{0}", 42), // 输出 "{42" format("Mix {{0}} and {0}", 42), // 输出 "Mix {0} and 42" format("{0}", "With { in value"), // 输出 "With { in value" ]); // 错误场景测试 try { format("Invalid closing brace }"); } catch (e) { console.log(e.message); // 输出 "Invalid closing brace }" } try { format("Invalid placeholder {z}"); } catch (e) { console.log(e.message); // 输出 "Invalid placeholder {z}" } try { format("{0} {1}", 42); } catch (e) { console.log(e.message); // 输出 "Not enough arguments" }
关键修复说明
转义逻辑实现
通过正则/({{)|(}})|{(\d+)}/g同时匹配三种场景:- 连续两个左大括号
{{:替换为单个{ - 连续两个右大括号
}}:替换为单个} - 标准数字占位符
{数字}:替换为对应索引的参数值
- 连续两个左大括号
前置错误检查
- 用
/(?<!{)}(?!})/g匹配无对应开括号的单独},直接抛出错误 - 用
/{([^}\d]+)}/g匹配包含非数字内容的无效占位符(如{z}),精准报错
- 用
参数索引校验
转换占位符索引为整数后,检查是否超出传入参数的数量,避免索引越界问题
内容的提问来源于stack exchange,提问作者Steve B
相关产品推荐
相关产品推荐

