简单词用str_replace,模糊匹配、忽略大小写或空格需用preg_replace;预处理应清理空格标点但保留中文和emoji;词库按长度倒序排列并批量替换;注意编码统一为utf-8并检查输入转义。

敏感词替换用 str_replace 还是 preg_replace?
简单词、固定词用 str_replace;带模糊匹配(如“*妈”“老*”)、需忽略大小写或中间空格的,必须上 preg_replace。前者快且安全,后者灵活但容易写错正则导致崩溃或漏匹配。
-
str_replace适合:黑名单是完整词,比如['傻逼', '尼玛', '操'],直接替换成 *** -
preg_replace才能处理:用户输“shǎbī”、“傻 逼”、“s h a b i”,或想匹配“操[任意1-2字符]”这种模式 - 正则注意加
i修饰符(忽略大小写),用\s*处理空格,避免写/傻.*?逼/i这种贪婪匹配——可能跨词误杀
脏话中间插空格/符号怎么过滤?
用户早就不按常理出牌了,str_replace 对 “傻 逼” 或 “傻@逼” 完全无效。得先做预处理,再进核心过滤。
- 统一清理:用
preg_replace('/[\s\p{P}]+/u', '', $text)去掉所有空白和常见标点(\p{P}匹配 Unicode 标点) - 或者更保守:只替换空格和常见分隔符,比如
str_replace([' ', '\t', ' ', '@', '.', '_'], '', $text) - 别一上来就删所有非字母数字——会把中文、emoji 全干掉,导致乱码或误判
性能差、卡顿,是不是词库太大了?
真卡,大概率不是代码问题,而是词库没做分级或用了低效遍历。1000 条词用 str_replace 数组一次过,比循环调用快 5–10 倍。
- 把敏感词按长度倒序排列(长词优先),避免“花生”被“花”提前替换了,导致“花生油”变“***生油”
- 别用
foreach+str_replace逐个替换,改用str_replace($badWords, str_repeat('*', mb_strlen($badWords[0])), $text)批量操作 - 词库超 2000 条?考虑用 Aho-Corasick 算法(PHP 有
ext-aho-corasick扩展),但多数场景纯数组够用
为什么测试时能过滤,上线就漏掉?
多半是编码或上下文环境不一致:本地 UTF-8,线上可能是 GBK;或者用了 mb_ 函数但没设默认编码,导致中文截断、匹配失败。
立即学习“PHP免费学习笔记(深入)”;
- 确认
mb_internal_encoding('UTF-8')在入口文件开头就调用,否则mb_strlen等函数行为不可靠 - 检查输入是否经过
trim()和html_entity_decode()—— 用户粘贴的 “ ” 或 “〹” 不处理,词根本对不上 - 日志里打出来实际进过滤函数的字符串,别只看前端传来的原始 POST 值——中间可能被框架自动转义过











