preg_split 用 PREG_SPLIT_DELIM_CAPTURE 保留分隔符的关键是将分隔符置于捕获组()内并传入该标志;未加标志或未括号则分隔符被丢弃;多捕获组按序独立成项;字面量分隔符需 preg_quote 转义;注意空项处理、性能开销及 Unicode 兼容性。

用 preg_split 的 PREG_SPLIT_DELIM_CAPTURE 标志
直接保留分隔符的关键是捕获分组 + 拆分标志。把分隔符写进带括号的子模式里,再传入 PREG_SPLIT_DELIM_CAPTURE,就能让分隔符也作为独立元素出现在结果数组中。
常见错误是只写 preg_split 但没加标志,或者分隔符没用括号包裹——那样分隔符会被丢弃,得不到“保留”效果。
- 分隔符必须放在
()内,例如/(\s+)/、/([,;]+)/ - 必须传第四个参数
PREG_SPLIT_DELIM_CAPTURE,否则括号只用于分组,不参与结果输出 - 如果正则有多个捕获组,每个匹配到的组都会单独成为数组一项(按顺序)
$str = "a,b;c";
$result = preg_split('/([,;])/', $str, -1, PREG_SPLIT_DELIM_CAPTURE);
// → ['a', ',', 'b', ';', 'c']
分隔符是固定字符串时别硬套正则
如果只是想按某个字面量(比如 "::" 或 "|")分割并保留它,用 preg_quote 转义再构造正则更安全。否则特殊字符(如 .、*、+)会触发意外匹配。
- 直接拼接未转义的字符串进正则,可能导致语法错误或逻辑错乱,例如
"/$sep/"中$sep = "."会变成"/./",匹配任意单字符 - 用
preg_quote($sep, '/')确保字面量含义,斜杠是正则定界符,必须指定为第二个参数 - 注意空字符串分隔符会引发警告,需提前判断
$sep = "::";
$pattern = '/(' . preg_quote($sep, '/') . ')/';
$result = preg_split($pattern, $str, -1, PREG_SPLIT_DELIM_CAPTURE);
需要过滤空项时注意分隔符位置影响
当字符串开头、结尾或连续出现分隔符时,preg_split 默认会产生空字符串元素。是否保留这些空项,取决于业务场景——比如解析日志行时可能要留,做命令行参数拆分时往往要剔除。
立即学习“PHP免费学习笔记(深入)”;
- 加
PREG_SPLIT_NO_EMPTY可去掉所有空字符串,但它会同时干掉合法的空字段(如"a,,b"中间的"") - 更稳妥的是拆完再用
array_filter($result, 'strlen'),但要注意这也会过滤掉纯空白字符串(如" ") - 若需区分“空”和“空白”,得用回调函数手动判断,不能依赖默认过滤
性能与兼容性:比 explode 慢,但 PHP 5.2+ 都支持
preg_split 带捕获的开销明显高于 explode,尤其在长字符串或高频调用场景下。如果分隔符完全固定且无正则需求,优先考虑自己手写循环 + strpos + substr 模拟,反而更快更可控。
- PHP 5.2 起就支持
PREG_SPLIT_DELIM_CAPTURE,老环境不用额外降级处理 - 注意 PCRE 库版本差异:极旧系统(如 CentOS 6 默认 PCRE 7.x)对 Unicode 分隔符支持弱,中文标点慎用 \p{P} 类断言
- 如果分隔符本身含 Unicode 字符(如 emoji 或中文顿号),确保字符串是 UTF-8 编码,并在正则前加
u修饰符,例如'/([\x{FE00}-\x{FE0F}])/u'
真正麻烦的不是语法怎么写,而是分隔符边界模糊时——比如想按空格切但忽略全角空格、不间断空格、制表符混用的情况。这时候正则得写一堆 Unicode 类,还容易漏,不如先 normalize 空白再统一处理。



















