在PHP开发中,我们经常会遇到需要在字符串的指定位置插入新字符的场景,比如给手机号中间加分隔符、在身份证号特定位置加空格等。很多开发者习惯用preg_match配合正则实现,但正则的写法相对繁琐,而且执行效率不如PHP原生的字符串处理函数。其实不用正则也能优雅地完成这个需求,下面介绍几种常用的实现方案。

方法一:使用substr分割拼接
substr是PHP最基础的字符串截取函数,我们可以通过截取指定位置前后的子串,再和要插入的字符拼接,就能实现插入效果。这种方法适合处理纯英文、数字等单字节字符串。
<?php
/**
* 单字节字符串指定位置插入字符
* @param string $str 原字符串
* @param int $pos 插入位置,从0开始计数
* @param string $insert 要插入的字符
* @return string
*/
function insert_str_by_substr($str, $pos, $insert) {
// 截取位置前的子串
$front = substr($str, 0, $pos);
// 截取位置后的子串
$after = substr($str, $pos);
// 拼接返回
return $front . $insert . $after;
}
// 示例:给手机号中间加横杠,原手机号13800138000,在第3位后插入-
$phone = '13800138000';
$result = insert_str_by_substr($phone, 3, '-');
echo $result; // 输出138-00138000
?>方法二:使用mb_substr处理多字节字符串
如果字符串包含中文、 emoji等多字节字符,用substr会出现乱码,因为substr是按字节截取的,而中文在UTF-8编码下占3个字节。这时候需要用mb_substr,它支持按字符数截取,避免乱码问题。
<?php
/**
* 多字节字符串指定位置插入字符
* @param string $str 原字符串
* @param int $pos 插入位置,从0开始计数
* @param string $insert 要插入的字符
* @param string $encoding 字符编码,默认UTF-8
* @return string
*/
function insert_str_by_mb_substr($str, $pos, $insert, $encoding = 'UTF-8') {
// 截取位置前的子串,按字符数截取
$front = mb_substr($str, 0, $pos, $encoding);
// 截取位置后的子串
$after = mb_substr($str, $pos, null, $encoding);
// 拼接返回
return $front . $insert . $after;
}
// 示例:给中文昵称中间加符号,原昵称是「张三李四」,在第2个字符后插入★
$nickname = '张三李四';
$result = insert_str_by_mb_substr($nickname, 2, '★');
echo $result; // 输出张三★李四
?>方法三:使用str_split转为数组后插入
还可以先把字符串转为字符数组,再用array_splice在指定位置插入元素,最后拼接回字符串。这种方法逻辑更直观,同样需要注意多字节字符串的处理。
<?php
/**
* 用数组方式实现字符串指定位置插入字符(多字节版本)
* @param string $str 原字符串
* @param int $pos 插入位置,从0开始计数
* @param string $insert 要插入的字符
* @param string $encoding 字符编码,默认UTF-8
* @return string
*/
function insert_str_by_array($str, $pos, $insert, $encoding = 'UTF-8') {
// 把字符串转为字符数组
$arr = preg_split('/(?<!^)(?!$)/u', $str);
// 在指定位置插入元素
array_splice($arr, $pos, 0, $insert);
// 拼接数组为字符串
return implode('', $arr);
}
// 示例:给混合字符串插入字符,原字符串是「abc中文123」,在第5个字符后插入_
$mixed_str = 'abc中文123';
$result = insert_str_by_array($mixed_str, 5, '_');
echo $result; // 输出abc中文_123
?>不同方法对比
下面是三种方法的适用场景和特点对比:
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| substr拼接 | 纯单字节字符串(英文、数字) | 执行效率最高,代码简洁 | 处理多字节字符串会乱码 |
| mb_substr拼接 | 包含多字节字符的字符串 | 支持中文等多字节字符,无乱码 | 比substr稍慢,需要指定编码 |
| 数组插入 | 复杂字符场景,逻辑更直观的需求 | 逻辑清晰,容易扩展 | 性能略低于前两种方法 |
注意事项
- 插入位置pos的取值要在0到原字符串长度之间,否则会出现异常,建议插入前做边界校验。
- 处理多字节字符串时,优先选择mb_substr或者数组方式,避免用substr导致乱码。
- 如果插入位置是动态计算的,比如需要找到某个字符第一次出现的位置再插入,可以先用
strpos(单字节)或者mb_strpos(多字节)获取位置,再调用上述方法。
通过以上几种方法,我们可以在不用preg_match的情况下,优雅地完成PHP字符串特定位置插入字符的需求,相比正则方案,代码更简洁,执行效率也更高,大家可以根据实际场景选择最合适的实现方式。