登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  php教程

PHP mb_str_split 如何保留分隔符并控制偏移

来源:17golang原创

时间:2026-09-14 11:32:34 164浏览 收藏

我第一次在接口里处理“中文标题,按第几个字符开始,再把逗号保留”的需求时,差点把 mb_str_split() 当成了带 separatoroffset 的增强版 explode()。实际签名只有字符串、每块字符数和编码三个参数。要控制起点,先用 mb_substr();要保留分隔符,再用带捕获组的 preg_split()。这样中文、英文和 emoji 的位置都按字符处理。

官方手册:https://www.php.net/manual/en/function.mb-str-split.php

要点速览
  • mb_str_split()length 是字符数,不是字节数,不能直接传分隔符或偏移量。
  • 从第 N 个字符开始处理,用 mb_substr($text, $offset, null, 'UTF-8'),偏移从 0 开始。
  • 保留分隔符,用 preg_split() 的捕获组和 PREG_SPLIT_DELIM_CAPTURE,再明确连续分隔符是否保留空项。

mb_str_split 先做字符级切分,但它没有 offset 和 separator

如果目标只是把多字节字符串按字符或固定字符数切块,mb_str_split($text, 2, 'UTF-8') 就够了。第三个参数建议显式写出,避免调用方依赖运行时的内部编码。它返回的是字符块数组,不会理解“逗号是分隔符”,也不会从指定偏移开始。

PHP mb_str_split、mb_substr 与 mb_strpos 按 UTF-8 字符处理参数的关系示意图
图1:参数关系示意图,mb_str_split 负责按字符分块,偏移由 mb_substr 或 mb_strpos 处理。

这里的 2 表示两个字符,不是两个字节。若输入包含中文,改用 str_split() 会把 UTF-8 字节拆开,后续输出可能出现乱码。

按字符偏移开始处理,先截取再切分

“从第 5 个字符开始”与“找到第二个逗号后开始”是两种不同需求。前者可直接使用 mb_substr();后者先用 mb_strpos() 查到字符位置,再把位置交给 mb_substr()。这两个函数的坐标都是字符坐标,不能和 strlen()strpos() 的字节坐标混用。

偏移点恰好落在分隔符上时,要先定规则:是把这个分隔符算进结果,还是从它后面的内容开始。对日志、标签和订单备注,我通常让偏移先截取,再做分隔符拆分,规则最容易复现。

用 preg_split 捕获分隔符,再决定是否过滤空项

preg_split() 默认会丢掉匹配到的分隔符;把分隔符放进正则捕获组,并传入 PREG_SPLIT_DELIM_CAPTURE 后,分隔符会按原样成为数组元素。中文逗号、英文逗号可以放在同一个字符类里,正则末尾的 u 表示按 UTF-8 处理。

PHP preg_split 捕获中文逗号并让分隔符进入 token 数组的关系示意图
图2:分隔符保留示意图,捕获组让原始分隔符和文本片段一起进入结果数组。

PREG_SPLIT_NO_EMPTY 会过滤空字符串。若文本可能出现连续分隔符,先去掉这个标志并在业务层保留空项,才能区分“两个分隔符之间确实没有内容”和“输入尾部多了一个分隔符”。

把偏移与分隔符策略封装成一个小接口

如果调用处反复出现“先截取、再拆分”,可以封装成一个函数。它不伪装成 mb_str_split() 的新参数,而是明确说明:offset 是字符下标,delimiter 是字面分隔符,返回数组包含内容和分隔符。

需求合适函数关键边界
按字符定长切块mb_str_splitlength 大于 0,按字符计数
从字符位置开始mb_substroffset 从 0 开始,可为负
查找多字节分隔符mb_strpos未找到返回 false
保留分隔符preg_split捕获组加 PREG_SPLIT_DELIM_CAPTURE

相关问题

mb_str_split 能直接传 offset 吗?

不能。它的第二个参数是每块的字符长度,不是起始位置;先用 mb_substr() 截取剩余字符串。

为什么结果里的中文分隔符消失了?

因为 preg_split() 默认移除匹配内容。使用捕获组和 PREG_SPLIT_DELIM_CAPTURE 才会把分隔符放回数组。

emoji 能按一个字符处理吗?

mb_* 函数按 Unicode 代码点处理,并不等于用户感知的完整字形;需要按字素簇切分时,应另行评估 grapheme_* 系列函数。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>