preg_split默认保留空字符串,因其忠实反映正则匹配位置,将所有分割点间子串(含长度为0的)均纳入结果;需显式添加preg_split_no_empty标志过滤。

preg_split 默认保留空字符串的原因
preg_split 在 PHP7.4 中默认不会自动过滤掉因连续分隔符或开头/结尾匹配产生的空字符串。比如用 /s+/ 切分 " a b ",结果是 ['', 'a', 'b', ''],不是你想要的 ['a', 'b']。这不是 bug,而是设计行为:它忠实反映正则匹配位置,把所有分割点之间的子串(包括长度为 0 的)都放进结果数组。
关键在于:空元素是否出现,取决于你的模式是否能“零宽匹配”或在字符串边界匹配成功。
PREG_SPLIT_NO_EMPTY 是最直接的解决方式
这个标志告诉 preg_split 跳过所有长度为 0 的元素,不用额外 array_filter()。
- 必须作为第 4 个参数传入,类型是
int,不能写成字符串 "PREG_SPLIT_NO_EMPTY"
- 只过滤空字符串,不处理仅含空白字符的字符串(如
"
")
- 和
PREG_SPLIT_DELIM_CAPTURE 可共存,但注意捕获组本身也可能产生空项
$str = " apple, , banana,,cherry ";
$result = preg_split('/[,\s]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
// → ['apple', 'banana', 'cherry']
需要同时 trim 和去重?别只靠一个 flag
PREG_SPLIT_NO_EMPTY 不会帮你去掉每个元素首尾空格,也不会合并重复值。如果你的原始字符串有类似 " x , y , x " 这种结构,得组合处理:
- 先用
PREG_SPLIT_NO_EMPTY 去掉空项
- 再用
array_map('trim', ...) 清理每个元素
- 如果要去重且保持顺序,跟在后面加
array_values(array_unique(...))
- 注意:
trim() 对 null 或非字符串类型会出 warning,确保输入是字符串
$str = " x , y , x ";
$result = array_values(
array_unique(
array_map('trim', preg_split('/[,\s]+/', $str, -1, PREG_SPLIT_NO_EMPTY))
)
);
// → ['x', 'y']
为什么不用 array_filter($arr, 'strlen')?
有人习惯写 array_filter($arr, 'strlen') 来清空数组,这在大多数情况下确实有效,但有隐患:
- 如果数组里本来就有值为
0、false、null 的合法元素(比如数字 ID),strlen(0) === 0,会被误删
-
array_filter 不会重排键名,返回的是关联数组,可能破坏后续索引访问逻辑
- 多一次遍历,性能略差(对小数组可忽略,但批量处理时值得留意)
-
PREG_SPLIT_NO_EMPTY 是 C 层原生支持,更轻量、语义更明确
真正容易被忽略的是:正则模式本身的设计。比如用 /s*,s*/ 替代 /[,\s]+/,虽然看起来更“精准”,但反而更容易在边界产生空项——尤其当字符串以逗号或空格开头结尾时。模式越复杂,越要先用 preg_match_all 验证分割点是否符合预期。
int,不能写成字符串 "PREG_SPLIT_NO_EMPTY"
"
")PREG_SPLIT_DELIM_CAPTURE 可共存,但注意捕获组本身也可能产生空项PREG_SPLIT_NO_EMPTY 不会帮你去掉每个元素首尾空格,也不会合并重复值。如果你的原始字符串有类似 " x , y , x " 这种结构,得组合处理:
- 先用
PREG_SPLIT_NO_EMPTY去掉空项 - 再用
array_map('trim', ...)清理每个元素 - 如果要去重且保持顺序,跟在后面加
array_values(array_unique(...)) - 注意:
trim()对null或非字符串类型会出 warning,确保输入是字符串
$str = " x , y , x ";
$result = array_values(
array_unique(
array_map('trim', preg_split('/[,\s]+/', $str, -1, PREG_SPLIT_NO_EMPTY))
)
);
// → ['x', 'y']
为什么不用 array_filter($arr, 'strlen')?
有人习惯写 array_filter($arr, 'strlen') 来清空数组,这在大多数情况下确实有效,但有隐患:
- 如果数组里本来就有值为
0、false、null 的合法元素(比如数字 ID),strlen(0) === 0,会被误删
-
array_filter 不会重排键名,返回的是关联数组,可能破坏后续索引访问逻辑
- 多一次遍历,性能略差(对小数组可忽略,但批量处理时值得留意)
-
PREG_SPLIT_NO_EMPTY 是 C 层原生支持,更轻量、语义更明确
真正容易被忽略的是:正则模式本身的设计。比如用 /s*,s*/ 替代 /[,\s]+/,虽然看起来更“精准”,但反而更容易在边界产生空项——尤其当字符串以逗号或空格开头结尾时。模式越复杂,越要先用 preg_match_all 验证分割点是否符合预期。
0、false、null 的合法元素(比如数字 ID),strlen(0) === 0,会被误删array_filter 不会重排键名,返回的是关联数组,可能破坏后续索引访问逻辑PREG_SPLIT_NO_EMPTY 是 C 层原生支持,更轻量、语义更明确php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











