最直接方案是用 std::regex_replace 配合不区分大小写的正则 r"()" 清除 script 标签;但其不处理注释、cdata 和 xss 属性,且对恶意输入易栈溢出。> ↩

用 std::regex_replace 清除 HTML 标签最直接
如果你确定输入是近似 HTML 的文本(比如含 <script></script>、、<script type="text/javascript"></script> 等变体),且编译器支持 C++11 及以上、启用了正则库,std::regex_replace 是最简方案。它能一次性匹配并移除开闭标签及中间内容。
注意:C++ 标准正则对回溯控制弱,复杂嵌套或恶意构造的标签可能引发栈溢出或性能骤降;不推荐用于不可信的长输入。
示例:
std::string html = "Hello<script>alert(1)</script>World<script src="%5C%22x.js%5C%22"></script>"; std::string clean = std::regex_replace(html, std::regex(R"(?script[^>]*>)", std::regex_constants::icase), ""); // 结果:"HelloWorld"
-
R"(...)"避免双重转义,[^>]*防止跨标签匹配 -
std::regex_constants::icase让<script></script>和<script></script>都命中 - 该正则不处理注释内脚本或 CDATA 区域,也不防
<img onerror="...">类 XSS
手写循环 + find/erase 更可控、无依赖
当不能用正则(如嵌入式环境、禁用 STL regex)、或需精确控制边界(比如只删完整成对标签,跳过误匹配的 <scripting></scripting>)时,手动扫描更稳妥。
核心逻辑是反复查找 "<script> 开头,再找对应 <code>">"</script>,然后查找闭合 ""(忽略大小写),最后擦除整段。关键在大小写不敏感比较和嵌套容错。
示例要点:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 用
std::search+std::toupper实现大小写无关查找,避免std::string::find的大小写敏感限制 - 必须检查开标签后是否紧跟
>或空格/换行/属性,防止匹配到单词内部(如javascript) - 闭合标签要从开标签结束位置之后开始搜,否则会匹配到自身(
<script></script>中第一次就找到) - 每次擦除后索引重置,避免越界或漏删嵌套(如
<script><script></script>)
为什么不用 boost::regex 或第三方 HTML 解析器
Boost 正则虽比标准库强,但依然不是 HTML 解析器——它无法识别标签结构、属性引号配对、注释、CDATA,容易被 <script><!-- <script> --></script> 这类构造绕过。
真正安全的方案是用 HTML 解析器(如 htmlcxx、libxml2),但代价高:
- 引入外部依赖,编译链变重
- 解析后需遍历 DOM 删除
script节点,再序列化回字符串,性能开销大 - 多数轻量场景不需要保真解析——只要“看起来像脚本标签的都干掉”即可
所以除非你在写 Web 代理或安全网关,否则正则或手写扫描已够用。
容易被忽略的边界情况
真实数据里常出现这些导致漏删或误删的情况:
-
<script comment></script>—— 注释中断标签,标准正则[^>]*会停在//前,但实际浏览器仍执行。需扩展匹配逻辑(如允许//后任意字符直到>) -
<script><script></script>—— 实体编码的内层标签不会执行,但若后续有解码环节,就得提前处理实体 - UTF-8 BOM 或非 ASCII 空白符(如
零宽空格)夹在和 <code>script之间,会使简单子串查找失效 -
<script src="a.js"></script>中的src属性值含>(如 base64 数据)——此时正则[^>]*会截断,应改用引号配对解析
如果输入来源不可控,别只靠字符串操作;至少加一层白名单过滤(如只保留字母、数字、常见标点)再处理。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










