正则表达式在轻量级模板渲染器中承担定位占位符、提取变量路径、触发替换三重角色,核心是匹配结果准确映射数据结构并安全可控替换;支持空格、点号路径与可选过滤器,避免贪婪匹配与未闭合误判;变量路径通过 split('.') 和 reduce 安全求值,fallback 为空字符串;默认 html 转义防 xss,三重大括号绕过转义;不支持条件/循环语法,禁用 eval,采用单次全局匹配提升性能。

正则表达式在轻量级模板渲染器中承担“定位占位符 + 提取变量路径 + 触发替换”三重角色,核心不是写多复杂的正则,而是让匹配结果能准确映射到数据结构,并安全、可控地完成替换。
占位符识别:从简单匹配到鲁棒提取
最基础的模板如 "Hello {{name}}",用 /{{(\w+)}}/g 即可捕获 name;但真实场景中常出现空格、点号路径或过滤器,比如 {{ user.profile.name | uppercase }}。这时需升级正则:
-
/{{\s*([\w.]+)\s*(?:\|\s*(\w+))?\s*}}/g—— 支持前后空格、点号路径(如user.profile)、可选过滤器(如uppercase) - 避免误匹配:不用
.*?这类贪婪通配,防止跨占位符吞掉内容;也不匹配{{后无闭合的情况 - 分组设计要明确:
$1是变量路径,$2是过滤器名,便于后续逻辑分流
变量求值:把字符串路径转成真实数据
匹配出 "user.profile.name" 只是字符串,需把它安全转为 data.user.profile.name 的值:
- 用
.split('.')拆成['user', 'profile', 'name'] - 用
reduce((obj, key) => obj?.[key], data)逐层访问,?.防止中间某层为null或undefined导致报错 - 始终 fallback 到空字符串(如
?? ''),避免模板渲染中断或输出"undefined"
安全与扩展:防 XSS 和支持基础逻辑
直接插入用户数据可能执行恶意脚本,尤其模板来自外部时:
- 默认对所有插值做 HTML 转义:把
&→&、→ <code>、<code>>→> - 若需原样输出 HTML(如富文本字段),约定三重大括号语法
{{{html}}},单独用另一条正则匹配并跳过转义 - 过滤器逻辑在 replace 回调中判断:
if (filter === 'uppercase') return value?.toUpperCase(),保持主流程干净
性能与边界:为什么不用更高级语法
轻量级定位决定了能力边界:
- 不支持
{{#if}}、{{#each}}等条件/循环——那需要语法解析器,正则无法可靠处理嵌套结构 - 不推荐用
eval或Function执行表达式,破坏沙箱且易引入漏洞 - 批量替换优于多次
replace调用:一次正则全局匹配 + 单次replace回调,避免重复扫描字符串











