preg_split默认保留空字符串,因连续分隔符间存在零长度子串;加PREG_SPLIT_NO_EMPTY可过滤;需注意中英文破折号Unicode差异,推荐用/[-–—―−]/u匹配并加/u修饰符。
默认情况下 preg_split 不会自动过滤空项,比如 "a--b" 用 '/-/' 分割,结果是 ['a', '', 'b']。这不是 bug,是正则匹配的自然行为——两个连续破折号之间确实存在一个长度为 0 的子串。
解决方法很简单:加 PREG_SPLIT_NO_EMPTY 标志:
$parts = preg_split('/-/', $text, -1, PREG_SPLIT_NO_EMPTY);
array_map('trim', ...)
常见误区是只写 '/-/',但实际文本中可能混着全角破折号(—)、en dash(–)、em dash(—)、甚至中文顿号或减号(−)。它们 Unicode 码位不同,正则不会匹配。
稳妥做法是显式列出常用变体:
$pattern = '/[-–—―−]/u'; // 支持 ASCII 减号、en dash、em dash、全角连接号、Unicode 减号
/u 修饰符必须加,否则 UTF-8 中文破折号会匹配失败或乱码'/-/',但上线前务必检查原始数据来源mb_ereg_replace 或 str_replace 预处理统一成一种再分割,有时比写复杂正则更稳默认 preg_split 丢弃分隔符。如果需要像 "a-b-c" → ['a', '-', 'b', '-', 'c'] 这样保留破折号本身,得靠捕获组和标志配合:
$parts = preg_split('/(-)/u', $text, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
- 包成捕获组,PREG_SPLIT_DELIM_CAPTURE 让它也进结果数组PREG_SPLIT_NO_EMPTY,避免因开头结尾是破折号产生空项[-–—]),捕获组会把实际匹配到的那个字符原样返回,适合做后续类型判断如果只是简单按 ASCII 破折号切分,且确认输入无 Unicode 异常,

explode('-', $text) 比 preg_split 快 3–5 倍,内存占用更低。
explode 不支持正则,不能处理多种破折号变体,也不能保留分隔符array_filter(array_map('trim', explode('-', $text))) 依然比正则快preg_split 的典型场景只有两个:需要多字符/多形态分隔符,或必须保留分隔符本身线上高频调用的接口里,先 mb_strpos($text, '–') 判断是否存在非 ASCII 破折号,再决定走 explode 还是 preg_split,是个实用的平衡点。