使用正则表达式移除不在允许列表中的HTML标签
移除非允许HTML标签的正则问题解决
需求说明
需要移除所有不在指定允许列表中的HTML开始/结束标签(包含标签属性),允许标签列表如下:
const allowedTags = ['a', 'b', 'i', 's', 'u', 'sup', 'sub', 'strong', 'cite', 'code', 'del', 'em'];
示例
输入:
<b><i><img src="http://example.com"/>Test<strong>Passed</strong><span>without any errors</span><a href="http://example.com">click here</a></b></i>
期望输出:
<b><i>Test<strong>Passed</strong>without any errors<a href="http://example.com">click here</a></b></i>
原有尝试代码
你写出的正则代码如下:
let regex = new RegExp(`<\/?(?!${allowedTags.join('|')})[^>]*>`, 'g') str.replace(regex, '')
你对正则各部分的预期逻辑:
<:匹配标签的起始字符<\/?:可选匹配闭合标签的/字符(?!${allowedTags.join('|')}):通过负前瞻排除允许列表中的标签[^>]*:匹配标签内除>外的所有内容(用于覆盖标签属性)>:匹配标签的结束字符>
问题分析
原有正则存在漏洞:负前瞻仅检查了紧跟在 </</ 后的起始字符串,但未限制标签名的边界。比如遇到类似 <stronginvalid> 这类以允许标签开头的非法标签时,正则会误判其为允许标签而保留,导致不符合预期的结果。
修正后的正则方案
调整正则,确保负前瞻能准确识别完整的允许标签名,避免前缀匹配的问题:
const allowedTagsPattern = allowedTags.join('|'); // 匹配非允许标签,处理标签名后接空格(属性)、>/(自闭合)的情况 const regex = new RegExp(`<\/?(?!(?:${allowedTagsPattern})(?:\\s|>|\/))[^>]*>`, 'g'); const cleanedHtml = str.replace(regex, '');
修正点说明
- 新增
(?:\s|>|\/)部分:确保允许标签名的后续字符是空格(连接属性)、标签结束符>或自闭合的/,以此界定完整的标签名边界,避免误判前缀匹配的非法标签。 - 用
(?:...)非捕获组包裹允许标签列表和边界匹配,避免生成多余的捕获组,提升正则效率。
测试验证
用修正后的正则处理示例输入,会正确移除 <img> 和 <span> 标签,得到你期望的输出结果。
内容的提问来源于stack exchange,提问作者galalem
相关产品推荐
相关产品推荐

