2026-04-17 21:30:24
在JavaScript中,可使用正则表达式结合matchAll方法解析并提取复杂模板字符串内容,核心步骤如下:
构建正则表达式使用正则表达式/{{s*([^}]+)s*}}|([^{}]+)/g匹配两类内容:
模板标记:{{s*([^}]+)s*}}
{{和}}:转义匹配字面量{{和}}。
s*:匹配零个或多个空白字符(如空格、制表符)。
([^}]+):第一个捕获组,匹配{{和}}之间非}的字符(即变量名)。
普通文本:([^{}]+)
第二个捕获组,匹配非{和}的任意字符(即模板标记外的文本)。
|:逻辑“或”,确保匹配模板标记或普通文本。
/g:全局标志,匹配所有符合条件的子串。
使用matchAll获取匹配结果String.prototype.matchAll()返回迭代器,包含所有匹配项的详细信息(如完整匹配、捕获组、索引等)。通过扩展运算符[...input.matchAll(regex)]将其转为数组。示例输出:
[ ["{{ text1 }}", "text1", undefined, index: 0, ...], [" 123 ", undefined, " 123 ", index: 14, ...], ...]match[0]:完整匹配字符串(如{{ text1 }}或123)。
match[1]:若匹配模板标记,则存储变量名(如text1);否则为undefined。
match[2]:若匹配普通文本,则存储文本内容(如123);否则为undefined。
后处理匹配结果通过map操作根据捕获组类型处理匹配项:
模板标记:若match[1]存在,提取变量名并去除首尾空格,重新封装为{{变量名}}。if (match[1] !== undefined) { return `{{${match[1].trim()}}}`; // 输出如"{{text1}}"}
普通文本:若match[2]存在,直接返回原始文本(保留空格)。else if (match[2] !== undefined) { return match[2]; // 输出如" 123 "}
过滤空值:使用filter(Boolean)移除可能的空字符串(如连续分隔符导致的空匹配)。
完整代码示例
const input = `{{ text1 }} 123 {{text1}}{{text1}} {{ text1}}134`;const regex = /{{s*([^}]+)s*}}|([^{}]+)/g;const result = [...input.matchAll(regex)] .map(match => { if (match[1] !== undefined) { return `{{${match[1].trim()}}}`; } else if (match[2] !== undefined) { return match[2]; } return match[0]; }) .filter(Boolean);console.log(result); // 输出: ["{{text1}}", " 123 ", "{{text1}}", "{{text1}}", " ", "{{text1}}", "134"]注意事项与优化
变量名规范:若需限制变量名格式(如仅允许字母、数字、下划线),可将([^}]+)替换为([wd_]+)。
性能优化:对于长字符串或高频调用,需测试正则表达式性能;必要时拆分逻辑或使用更高效的解析方法。
错误处理:当前正则将不完整的{{或}}视为普通文本,若需严格校验格式,需增强正则或添加额外逻辑。
复杂场景:对于嵌套模板或条件逻辑,建议使用专用模板引擎(如Handlebars、EJS)。
总结:通过正则表达式的“或”操作符和捕获组,结合matchAll的全局匹配能力,可高效解析复杂模板字符串。后处理阶段根据匹配类型精细化处理内容,既能提取模板变量,又能保留原始文本格式,满足多样化需求。