You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP波斯语敏感词过滤正则求助:重复字符与单字空格处理

解决波斯语&英语混合场景下的正则问题

嘿,这两个问题其实都是多字节字符编码和正则匹配逻辑的坑,我帮你逐个修正:


问题1:波斯语重复字符无法去除

你原来的正则preg_replace('/(.)\1+/', '$1', $text)对英语有效,是因为英语是单字节字符,但波斯语属于UTF-8多字节字符,PCRE默认会把字符串拆成字节处理,导致(.)只能匹配单个字节,而不是完整的波斯语字符(比如ی是多个字节)。

修正方案:

给正则加上/u修饰符,让PCRE以UTF-8编码解析字符串,这样就能正确匹配单个波斯语字符:

$text = preg_replace('/(.)\1+/u', '$1', $text);

测试一下:输入امیییییییییین,处理后会变成امین,完全符合预期。

为什么mb_ereg_replace无效?因为mb_ereg系列函数的正则语法和PCRE略有不同,而且需要确保你的PHP环境正确设置了默认编码(比如mb_internal_encoding('UTF-8')),但用preg_replace加/u是更简单可靠的方案。


问题2:合并带空格的单字(如S E X → sex)

你原来的正则preg_replace('/( [a-zA-Zآ-ی] )\1+/', trim('$1'), $text)逻辑完全错了:\1+表示重复匹配第一个捕获组的内容,也就是只能匹配“ S S S”这种重复的带空格字符,而无法匹配“S E X”这种不同字符用空格分隔的场景。

修正方案:

我们需要匹配任意连续的单个目标字符(英语/波斯语),字符之间有一个或多个空格,然后去掉空格并统一转小写(如果需要)。这里用preg_replace_callback更灵活:

$text = preg_replace_callback('/(?:\s*[a-zA-Zآ-ی]\s*)+/u', function($match) {
    // 先去掉所有空格
    $cleanStr = preg_replace('/\s+/', '', $match[0]);
    // 转小写(英语需要,波斯语可根据需求去掉这行)
    return strtolower($cleanStr);
}, $text);

测试输入S E X,处理后会变成sex;如果是波斯语的ا م ی ن,会变成امین。

如果想更简洁,也可以用全局替换直接去掉字符间的空格(适合单次替换场景):

// 匹配“字符+空格+字符”的模式,替换成“字符字符”,全局处理
$text = preg_replace('/([a-zA-Zآ-ی])\s+([a-zA-Zآ-ی])/u', '$1$2', $text);
// 重复替换直到没有空格(因为一次替换只能处理相邻的两个字符)
while(preg_match('/([a-zA-Zآ-ی])\s+([a-zA-Zآ-ی])/u', $text)) {
    $text = preg_replace('/([a-zA-Zآ-ی])\s+([a-zA-Zآ-ی])/u', '$1$2', $text);
}

不过回调函数的方式更高效,只需要遍历一次字符串。


内容的提问来源于stack exchange,提问作者Mohammad Amin Ghaseminia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:53:28