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

如何让PHP的str_word_count()支持UTF-8并识别特殊字符

解决PHP 7中str_word_count()无法识别UTF-8特殊字符的词频统计问题

你的问题核心确实出在str_word_count()函数上——它默认只识别ASCII范围内的字母、数字和下划线作为单词的一部分,对UTF-8编码的特殊字符(比如Başka里的ş、Café里的é、weiß里的ß)以及包含点、数字、特殊符号的单词(比如J.J.Johanson、mike18、2€uros)处理得非常糟糕,要么截断单词,要么直接忽略这些非ASCII的部分。

下面是可行的解决方案,我推荐用正则分割的方式替代str_word_count():

方法一:使用preg_split结合Unicode正则分割单词

这种方式能完美支持UTF-8字符,还可以自定义允许出现在单词中的符号(比如点、撇号、欧元符号等),灵活性很高。

修改后的完整代码如下:

$freqData = array();
$keywords = "Başka, Başka, küskün küskün otomobil kaçtı buraya küskün otomobil neden kaçtı kaçtı buraya, oraya KISMEN @here #there J.J.Johanson hep. Danny:Where is mom? I don't know! Café est weiß for 2 €uros. My 2nd nickname is mike18.";
$letterCount = 5;

// 分割规则:匹配非Unicode字母、数字、点、撇号、欧元符号的字符作为分隔符
// u修饰符启用UTF-8模式,PREG_SPLIT_NO_EMPTY过滤空字符串
$words = preg_split('/[^\p{L}\p{N}\.\'€]+/u', $keywords, -1, PREG_SPLIT_NO_EMPTY);

foreach ($words as $word) {
    // 可选:统一转为小写,避免大小写导致的重复统计(比如KISMEN和kismen)
    $word = mb_strtolower($word, 'UTF-8');
    
    if (mb_strlen($word, 'UTF-8') >= $letterCount) {
        // 统计词频,存在则+1,不存在则初始化为1
        $freqData[$word] = isset($freqData[$word]) ? $freqData[$word] + 1 : 1;
    }
}

// 用print_r输出数组,替代原代码的echo $freqData(直接echo数组只会显示Array)
print_r($freqData);

代码说明:

  • 正则[^\p{L}\p{N}\.\'€]+:^表示取反,\p{L}匹配所有Unicode字母,\p{N}匹配所有Unicode数字,后面的\.\'€是允许出现在单词中的特殊符号,你可以根据需求添加或移除(比如不需要欧元符号就删掉€)。
  • mb_strtolower和mb_strlen确保对UTF-8字符串的处理正确,避免乱码或长度计算错误。
  • 原代码中echo $freqData的错误:直接输出数组会显示Array,改用print_r或var_dump才能看到实际的词频数据。

方法二:自定义字符集调用str_word_count()(局限性较大)

str_word_count()其实支持第三个参数指定额外的单词字符,但对于UTF-8的多字节字符来说,这个参数只能传入单字节字符,无法处理像ş、é这类多字节的特殊字符,所以只能解决部分简单场景(比如允许@、#这类符号),无法解决带重音的UTF-8单词问题,因此不推荐。

示例(仅作参考):

// 仅能添加单字节符号,无法处理多字节UTF-8字符
$words = str_word_count($keywords, 1, '@#€');

这样修改后,你的词频统计就能正确识别所有UTF-8特殊字符和包含特定符号的单词了。

内容的提问来源于stack exchange,提问作者Meek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:30:25