最简方案是 preg_replace('/ +/', ' ', $str) 配合 trim();若需匹配所有空白字符则用 '/\s+/',但会同时处理制表符和换行符。

用 preg_replace 匹配连续空格并替换成单个空格
PHP 里不能靠 str_replace(' ', ' ', $str) 循环删多个空格,它只处理固定长度的字符串,对“两个以上”这种不定长模式无效。必须用正则,核心是匹配「一个及以上空格」,再统一替换成单个空格。
最常用写法:
$str = preg_replace('/\s+/', ' ', $str);但注意:\s 不仅匹配空格,还包括制表符、换行、回车等所有空白字符。如果只要处理纯空格(不碰 tab 或换行),得写成:$str = preg_replace('/ +/', ' ', $str);
- 正斜杠
/是分隔符,可换为其他符号(如# + #),但前后要一致 -
+表示“前面的字符出现一次或多次”,比*更精准(*允许零次,实际没意义) - 如果字符串首尾也有空格,这个正则不会自动 trim,得额外加
trim()
替换多个空格为其他字符(比如下划线)
场景常见于生成 URL 别名或文件名,要把空格转成 - 或 _,同时避免多个空格变成多个连接符。
直接改替换内容就行:
$slug = preg_replace('/ +/', '-', $str);但要注意:如果原字符串里已有 -,这样会把「空格+连字符+空格」也压成 --。更稳妥的做法是先统一空格,再替换:$slug = str_replace(' ', '-', preg_replace('/ +/', ' ', $str));立即学习“PHP免费学习笔记(深入)”;
- 别用
preg_replace('/ +/', '-', $str)直接上,容易产生多余连接符 - 如果还要兼容中文、字母数字以外的符号,建议先
mb_ereg_replace或用iconv转 ASCII 再处理
性能和编码注意点
小文本没问题,但处理大段日志或用户输入时,preg_replace 比 str_replace 慢不少。如果确定只处理 ASCII 空格且不涉及 Unicode,可以用 strtr 配合循环优化(不过多数情况没必要)。
- 确保源字符串编码是 UTF-8,否则
\s在 GBK 下可能误吞汉字 - 如果用
mb_ereg_replace,注意它已被 PHP 8.2 废弃,别在新项目里用 - 正则里写
/[[:space:]]+/和/\s+/效果一样,但前者更啰嗦,没必要
为什么不用 str_split + array_filter 这类数组操作
有人想把字符串切开、过滤空元素、再拼回去。这方法逻辑绕、内存占用高,还容易破坏原有换行结构——因为 array_filter 默认会删掉所有空字符串,包括你原本想保留的换行符。
-
explode(' ', $str)会产生大量空数组项,array_filter又不区分“空格产生的空项”和“本来就是空字符串”的情况 - 多字节字符(如中文)用
explode切割可能出错,preg_replace在 UTF-8 模式下更可靠 - 正则一行解决的事,拆成 4 行数组操作,可读性反而更低
实际用的时候,记住最简路径:preg_replace('/ +/', ' ', $str),再套一层 trim() 就够用了。复杂需求(比如保留段落换行但压缩行内空格)才需要加修饰符或分步处理。



















