1. 正则表达式提取 script 标签之间内容的基础
匹配模式的核心原理
在 HTML 文本中,script 标签的内容位于开始标签和结束标签之间,因此要实现提取,需要一个能够跨多行、跨字符的模式。核心原理是使用一个非贪婪的捕获组来取得开始标签与结束标签之间的文本。
常用思路是把开始标签用一个可选属性的匹配式捕获,然后用一个跨多行的捕获组取得内容,最后以结束标签收束。非贪婪模式和 跨行匹配是关键。
常用正则示例及解释
最常见的模式是:/<script\b[^>]*>([\\s\\S]*?)<\\/script>/gi。其中 ([\\s\\S]*?) 能捕获任意字符(包括换行),直到遇到最近的 </script> 为止。
使用它的过程通常是对整个 HTML 字符串执行替换或迭代,提取出 捕获组 1 的内容,即 script 标签内的代码。
const html = `<script type="text/javascript">console.log("hello");</script>`;
const regex = /<script\b[^>]*>([\\s\\S]*?)<\\/script>/gi;
const contents = [];
let m;
while ((m = regex.exec(html)) !== null) {contents.push(m[1]); // 这里是 script 标签之间的内容
}
console.log(contents);
处理不同标签属性的挑战
脚本标签的开始标签可能包含各种属性,例如 type, async, defer 等,因此开始标签的对齐正则要足够灵活,使用 边界词汇与 [^>]* 来忽略属性部分。
不过需要注意 正则对 HTML 的容错性有限,极复杂的文档结构可能导致错误匹配,因此在关键场景中应结合 DOM 解析或提升测试覆盖。
2. 正则提取的实战要点与常见坑
处理跨多行的脚本内容
脚本内容常包含换行、缩进和注释,[\s\S]*? 是对点对点的跨行匹配方案的常用替代。跨行匹配的需求在前端实时解析场景尤其常见。
一个更稳妥的写法是结合全局标志 gi,并在匹配失败时允许多次尝试,以确保所有脚本都被捕获。
避免误匹配边界与注释
如果 HTML 文本中出现了类似 的片段或注释,标准正则可能误读,导致提取出错。此时可以使用更严格的边界,例如只针对 <script 开头、</script> 结尾的段落来分组。
在示例中,若遇到多段同名脚本标签,应该采用全局匹配:/<script\\b[^>]*>([\\s\\S]*?)<\\/script>/gi,而不是仅匹配第一个。
性能与可维护性
对大文档执行全局正则会带来性能成本,尤其在服务端处理大量 HTML 时。因此在可控场景使用正则,并考虑与 DOM 解析结合以提升可维护性。
长期来看,将正则提取的结果交给后续的处理管线,如对脚本内容执行前进行验证和清洗,是一个更稳健的设计。
3. 在前端项目中的应用场景与注意事项
从 HTML 文本中提取并执行脚本的工作流
在某些单页应用中,需要动态提取服务器返回的 HTML 片段中的脚本并在特定环境下执行。此时用正则提取脚本内容只是第一步,后续需要对提取结果做严格的安全与执行控制。

把脚本提取为文本后,可以用 new Function 或 eval 来执行,但要防止潜在的 XSS 风险,务必在执行前对内容进行验签或仅在受信任的上下文中执行。
结合测试与安全审查
在前端流水线中,自动化测试是发现正则边界问题的关键。对异常输入如极长的字符串、包含 HTML 实体或特殊字符的情况进行覆盖测试。
此外,安全审查应当明确:哪怕正则成功提取了脚本内容,也不应直接执行,除非已经通过合规的清洗和授权流程。
// 将提取的脚本内容在白名单环境中执行的示例
const trustedScripts = [];
const scripts = extractScriptContents(html);
for (const s of scripts) {if (isTrusted(s)) {// 仅在受信任上下文中执行new Function(s)();}
}
4. 进阶替代方案:DOMParser 与 HTML 解析的对比
使用 DOMParser 提取 script 内容
尽管讨论的焦点是正则表达式,但在实际场景中,DOMParser 提供了更稳定的解析路径,能避免正则在极端 HTML 结构下的问题。
将字符串解析为文档后,可以直接使用 DOM API 读取 script 标签的 textContent,从而获得内容。
const htmlString = '<div><script>console.log(1)</script></div>';
const doc = new DOMParser().parseFromString(htmlString, 'text/html');
const scripts = [...doc.querySelectorAll('script')].map(s => s.textContent);
console.log(scripts);
正则与解析器的取舍
正则表达式在简单场景下非常高效,但对不规则的 HTML 容错能力有限,因此在复杂文档中优先考虑 DOM 解析,再在可控区域使用正则作为辅助。
对于前端构建工具或服务端渲染场景,统一使用解析器进行内容提取,可以减少潜在的边界错误和安全风险。


