PHP字符串替换问题:需排除特定17位字符内的目标子串
PHP字符串替换问题:排除特定17位字符内的目标子串
需求说明
需将字符串中所有B01至B99、L01至L99的子串替换为空格,需遵循以下规则:
- 替换所有B01-B99、L01-L99子串为空格,但排除固定长度17位的特殊字符(如示例中的
1JKFE4P03CDB05071)内部的对应内容 - 该17位字符长度固定为17,内部可能包含B01-B99、L01-L99或其他字符
- 该17位字符可出现在字符串任意位置,并非固定在末尾
- 处理的字符串为动态生成,非静态
现有问题
当前PHP代码会同时替换普通字符串和17位特殊字符内的目标子串(如B05),不符合需求。
测试数据
测试字符串
$teststr = "STTARB0520122012 HT 2021B0532B 31 01283H3 BU N EH 2 B 20000 1JKFE4P03CDB05071"; // 另一个测试用例 // $teststr = 'PARTSB052014B062014B07HTB062029B0532BB0831B0901283H3 BUB12N EH 5 B 90000B201FDFE4FS3CDB05071 ';
现有代码
<?php $teststr= "STTARB0520122012 HT 2021B0532B 31 01283H3 BU N EH 2 B 20000 1JKFE4P03CDB05071"; $teststr= 'PARTSB052014B062014B07HTB062029B0532BB0831B0901283H3 BUB12N EH 5 B 90000B201FDFE4FS3CDB05071 '; $barcodearr = array( "B01-B99"=>"", "L01-L99"=>"", ); foreach($barcodearr as $keycode=>$val) { if(strstr($keycode, '-')) { $barexp=explode("-",$keycode); $startarr = preg_split("/(,?\s+)|((?<=[a-z])(?=\d))|((?<=\d)(?=[a-z]))/i", $barexp[0]); $endarr = preg_split("/(,?\s+)|((?<=[a-z])(?=\d))|((?<=\d)(?=[a-z]))/i", $barexp[1]); $startnum=$startarr[1]; $endnum=$endarr[1]; $startstring=$startarr[0]; for($i=$startnum;$i<=$endnum;$i++) { $doblechar=$i; if(strlen($i)!=2){ $doblechar='0'.$i; } $findh=$startstring.$doblechar; if($startstring=='B'){ $space=''; for($j=1;$j<=$i;$j++) { $space.=' '; } $teststr=str_replace($findh,$space,$teststr); } } } } ?>
期望输出
$teststr = "STTAR 20122012 HT 2021 32B 31 01283H3 BU N EH 2 B 20000 1JKFE4P03CDB05071";
解决方案
核心思路
先通过占位符隔离17位特殊字符串,确保替换操作仅作用于普通文本部分,处理完成后再还原特殊字符串,避免误修改其内部内容。同时修正原代码中替换空格数量的逻辑(匹配期望输出,将每个Bxx/Lxx替换为与子串长度一致的两个空格)。
修正后的代码
<?php // 测试字符串 $teststr = "STTARB0520122012 HT 2021B0532B 31 01283H3 BU N EH 2 B 20000 1JKFE4P03CDB05071"; // $teststr = 'PARTSB052014B062014B07HTB062029B0532BB0831B0901283H3 BUB12N EH 5 B 90000B201FDFE4FS3CDB05071 '; // 1. 提取所有17位特殊字符串,用唯一占位符暂存 $placeholders = []; $placeholderIndex = 0; // 匹配17位字母数字组合(可根据实际字符范围调整正则) $teststr = preg_replace_callback('/[A-Z0-9]{17}/i', function($matches) use (&$placeholders, &$placeholderIndex) { $key = "__PLACEHOLDER_{$placeholderIndex}__"; $placeholders[$key] = $matches[0]; $placeholderIndex++; return $key; }, $teststr); // 2. 处理普通文本部分,替换B01-B99、L01-L99为两个空格(匹配期望输出) $teststr = preg_replace('/B(0[1-9]|[1-9]\d)/', ' ', $teststr); $teststr = preg_replace('/L(0[1-9]|[1-9]\d)/', ' ', $teststr); // 若需按原代码逻辑,替换为数字对应数量的空格,可使用以下回调替换: // $teststr = preg_replace_callback('/B(0[1-9]|[1-9]\d)/', function($matches) { // $num = intval($matches[1]); // return str_repeat(' ', $num); // }, $teststr); // $teststr = preg_replace_callback('/L(0[1-9]|[1-9]\d)/', function($matches) { // $num = intval($matches[1]); // return str_repeat(' ', $num); // }, $teststr); // 3. 还原占位符为原17位特殊字符串 foreach ($placeholders as $key => $value) { $teststr = str_replace($key, $value, $teststr); } // 输出结果 echo $teststr; ?>
代码说明
- 占位符隔离:通过
preg_replace_callback提取所有17位特殊串,用唯一占位符替换,确保后续替换操作不影响这些特殊内容。 - 正则替换:使用正则表达式精准匹配B01-B99、L01-L99,替换为符合期望的空格。
- 还原特殊串:遍历占位符数组,将占位符替换回原17位特殊字符串,完成最终处理。
内容的提问来源于stack exchange,提问作者userdev2025
相关产品推荐
相关产品推荐

