正则表达式用于敏感词过滤需预处理、边界控制与缓存:先转义元字符,用中文词边界避免跨词匹配;大规模词库须分片(≤200词/组)编译并缓存;应对绕过应优先文本清洗,高危词才启用有限模糊规则;替换策略需分级且保留上下文。

正则表达式在敏感词过滤中不是不能用,而是容易用错——尤其当词库变大、用户开始“花式绕过”时,简单拼接|的写法会迅速失效。真正实用的正则方案,核心在于预处理、边界控制和运行时缓存,而不是堆砌语法糖。
敏感词正则必须做转义和词边界
直接把“武汉|口罩|王*”拼成/武汉|口罩|王*/g是危险的:星号会被当作量词,点号、括号、问号等元字符会破坏匹配逻辑;更严重的是,“武汉”会误中“武汉市”,“口”可能单独命中“口罩”里的字。
- 每个敏感词需先转义:用
word.replace(/[.*+?^${}()|[]\]/g, '\$&')(JS)或preg_quote($word, '/')(PHP) - 中文场景推荐用
(?<=^|[u4e00-u9fa5s])词(?=$|[u4e00-u9fa5s])模拟词边界,避免跨词匹配 - 英文/混合内容可加
,但注意对中文无效,不能混用
大规模词库要分片编译,避免正则超长崩溃
上千个词硬塞进一个正则,不仅编译慢,某些引擎(如JavaScript的V8)还会触发回溯限制或内存溢出。实测超过500词后,new RegExp(words.join('|'))成功率明显下降。
- 按首字或分类分组:比如政治类200词一组、广告类300词一组,分别生成独立正则
- 每组词数控制在200以内,编译后缓存到Map或WeakMap中,键为分组标识
- PHP可用
array_chunk($keywords, 200)切块,循环调用preg_replace,比单次大正则更稳
应对绕过:正则支持干扰符容错,但要有节制
用户插入空格、全角符号、零宽字符(U+200B)、大小写混用,是常见绕过手段。纯精确匹配已不够用,但模糊正则写太松又易误杀。
- 文本预处理优先:统一转小写、去除零宽字符、替换全角空格为半角、清理★→*等干扰符
- 对高危词单独配置模糊规则,例如“敏[\s\u3000\*\u2605]{0,2}感[\s\u3000\*\u2605]{0,2}词”,不全局启用
- 禁用
.*?类贪婪匹配,防止回溯爆炸;必要时用(?:s*)?替代s*
替换策略要兼顾安全与可读性
一律替成***看似省事,但在评论、弹幕等场景下,可能破坏语义、引发误判,甚至被用于构造恶意HTML。
- 纯文本替换用
String.prototype.replace()或preg_replace()即可 - 含HTML的内容,先用DOMParser提取
textContent,过滤后再还原结构,避免<script>内字符串被误杀</script> - 支持分级替换:政治类→
[已屏蔽](不可逆),普通类→**,长词可保留首尾字如“王***锋” - 记录命中位置和原词,供人工复审或训练模型优化漏杀率

















