PHP如何按自定义规则拆分下划线分隔的特定格式字符串
字符串拆分规则说明
待处理字符串为下划线连接的结构化内容,拆分规则明确:
- 以唯一的双下划线
__为界,最后一段为$d(燃油类型) - 双下划线前的内容,第一个单下划线前的部分为
$a(地区名) - 剩余部分为品牌+地址:品牌段如果是
Circle_K格式则合并为Circle K作为$b,其余单段品牌直接取第一个片段作为$b - 品牌段之后的所有内容,先拆分驼峰格式(大写字母前补空格),再将所有单下划线替换为空格,拼接后得到
$c(地址信息)
测试用例
用例1
输入:kronobergslan_Preem_AlmhultS_Esplanaden__diesel
期望输出:
$a = kronobergslan $b = Preem $c = Almhult S Esplanaden $d = diesel
用例2
输入:kronobergslan_Circle_K_VaxjoSodra_Vallviksvagen_352_51_Vaxjo__diesel
期望输出:
$a = kronobergslan $b = Circle K $c = Vaxjo Sodra Vallviksvagen 352 51 Vaxjo $d = diesel
注:原示例中35251为笔误,按输入的下划线分隔规则,两个数字段应保留空格,如需连续拼接可在最后地址处理步骤加数字合并逻辑
原代码问题分析
原实现逻辑出错的核心原因有三点:
- 初始拆分直接用单下划线全局切割,把双下划线拆成空数组元素,导致数组下标完全混乱,后续硬编码
$parts[3]/$parts[10]这类固定下标取数,只要输入段数变化就会错位 - 特殊品牌
Circle K的合并逻辑硬编码操作固定下标,没有做内容校验和边界判断,兼容性极差 - 驼峰拆分、格式替换只处理了单个数组元素,后续地址段的格式完全没处理,漏了大量内容
正确实现思路与代码
这类结构化字符串处理遵循先切大段、再提固定值、最后处理特殊规则和格式的顺序,就不会出现逻辑混乱:
- 优先切分最无歧义的分隔符(双下划线),直接拿到
$d,避免全局拆分干扰结构 - 提取位置完全固定的
$a - 在剩余内容中按规则判断并提取品牌段
$b,不依赖固定下标 - 最后统一处理地址段的格式替换,避免边拆边改漏内容
PHP实现代码:
public function filter($call){ // 1. 优先按双下划线切分,直接拿到燃油类型$d $segments = explode('__', $call); $d = trim(end($segments)); $mainContent = reset($segments); // 2. 提取固定位置的地区名$a $mainParts = explode('_', $mainContent); $a = array_shift($mainParts); // 3. 提取品牌名$b,判断是否为需要合并的Circle K $b = array_shift($mainParts); if ($b === 'Circle' && !empty($mainParts) && $mainParts[0] === 'K') { $b .= ' ' . array_shift($mainParts); } // 4. 处理剩余地址段生成$c $cRaw = implode('_', $mainParts); // 驼峰拆分:大写字母前(非开头位置)补空格 $c = preg_replace('/(?<!^)([A-Z])/', ' $1', $cRaw); // 剩余单下划线全部替换为空格,合并多余空格 $c = trim(preg_replace('/[\s_]+/', ' ', $c)); return [ 'a' => $a, 'b' => $b, 'c' => $c, 'd' => $d ]; }
如果需要直接输出示例中的变量赋值格式,在拿到返回数组后拼接输出即可。
同类问题通用处理方法
遇到规则明确的字符串拆分问题,按优先级处理即可:
- 先找全局唯一、不会和其他规则冲突的分隔符,切分最大的逻辑块,从根源上避免下标混乱
- 提取位置完全固定、没有特殊规则的内容,减少后续处理的内容量
- 处理有特殊匹配规则的内容时,不要依赖固定数组下标,要基于内容本身判断,同时做好边界校验
- 格式替换、内容拼接类操作放到所有拆分逻辑完成后统一做,避免边拆边改导致内容遗漏
内容的提问来源于stack exchange,提问作者doley
相关产品推荐
相关产品推荐

