PHP使用substr处理含多字节特殊字符字符串异常的解决方法
问题原因
- 你混用了两种计数逻辑的字符串函数:
mb_stripos是多字节处理函数,返回的偏移量是按字符数统计的结果;而原生substr是单字节函数,偏移量按字节数统计,二者计数单位不匹配是异常的核心诱因。 - 你提到的长破折号(—)属于UTF-8三字节字符,1个字符占3字节:
mb_stripos计算偏移时只把它算1个字符位,而substr处理时需要跳过3字节才会到下一个字符,最终导致你传入的偏移量比实际字节偏移少了2位,切割结果整体右移。
修复方案
所有涉及多字节字符串的操作统一使用mb_前缀的多字节处理函数,切割字符串替换为mb_substr,同时显式指定编码为UTF-8避免环境默认编码异常。
修复后的代码示例:
<?php $str1 = "— lorem lorem Alice lorem lorem lorem loremlorem"; $str2 = "a lorem lorem Alice lorem lorem lorem loremlorem"; $str3 = " lorem lorem Alice lorem lorem lorem loremlorem"; // 统一使用多字节函数处理,显式指定UTF-8编码 $foundIndex = mb_stripos($str1, "Alice", 0, 'UTF-8'); var_dump(mb_substr($str1, $foundIndex - 6, 24, 'UTF-8'), $foundIndex); $foundIndex = mb_stripos($str2, "Alice", 0, 'UTF-8'); var_dump(mb_substr($str2, $foundIndex - 6, 24, 'UTF-8'), $foundIndex); $foundIndex = mb_stripos($str3, "Alice", 0, 'UTF-8'); var_dump(mb_substr($str3, $foundIndex - 6, 24, 'UTF-8'), $foundIndex);
修改后三个测试用例的输出结果会完全一致,也可以正常处理emoji等任意长度的UTF-8特殊字符。
内容的提问来源于stack exchange,提问作者Ionică Bizău
相关产品推荐
相关产品推荐

