You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP实现字符串数字按序替换为序号占位符的正则方案

问题核心

原有实现使用str_replace做替换时,是对字符串做全局子串匹配,不会识别完整数字块,会把长数字内部包含的短数字字符也替换掉,比如替换0时会把64000里的三个0也误替换。靠替换数组按长度/数值排序的方案存在边界缺陷,遇到数字间存在包含关系(比如同时存在12和2、123)时仍可能出错。

最优实现方案

使用preg_replace_callback配合数字-占位符映射表实现,正则\d+天然匹配完整连续数字块,从根本上避免子串误替换问题,同时天然支持相同数字复用同一个占位符。

完整实现代码

$text1 = "S0 64000";
$text2 = "C0 64000";
$numPattern = '/\d+/';

// 提取基准文本中的所有完整数字块
preg_match_all($numPattern, $text1, $originalNums);

// 构建数字到占位符的映射,相同数字仅分配一次占位符序号
$numPlaceholderMap = [];
$index = 0;
foreach ($originalNums[0] as $numStr) {
    if (!isset($numPlaceholderMap[$numStr])) {
        $numPlaceholderMap[$numStr] = "%d{$index}%";
        $index++;
    }
}

// 校验两个待处理文本的数字集合是否一致
preg_match_all($numPattern, $text2, $transNums);
$uniqueOriginal = array_unique($originalNums[0]);
$uniqueTrans = array_unique($transNums[0]);
sort($uniqueOriginal);
sort($uniqueTrans);
if ($uniqueOriginal !== $uniqueTrans) {
    dd("两个文本的数字集合不匹配");
}

// 执行正则回调替换,每次匹配完整数字块后从映射表取对应占位符
$newText1 = preg_replace_callback(
    $numPattern,
    fn($match) => $numPlaceholderMap[$match[0]],
    $text1
);
$newText2 = preg_replace_callback(
    $numPattern,
    fn($match) => $numPlaceholderMap[$match[0]],
    $text2
);

方案优势

  • 无替换错误:正则匹配逻辑只会识别连续的完整数字串,不会把长数字拆分为单个字符/短子串替换,完全规避str_replace的误替换问题
  • 无排序依赖:不需要对替换目标做长度、数值排序,不存在排序逻辑带来的边界bug
  • 逻辑简洁:通过关联数组映射天然实现相同数字复用同一占位符的需求,符合规则要求
  • 兼容性强:支持任意长度文本、任意位置的数字匹配,文本无数字时直接返回原内容,不需要额外特殊判断

场景验证

  • 输入"S0 64000",输出"S%d0% %d1%",符合预期
  • 输入"S0 0",输出"S%d0% %d0%",符合同数字复用占位符的要求
  • 输入"S10 455"/"C10 455",输出均为对应前缀加%d0% %d1%,满足后续占位符还原数值的需求

内容的提问来源于stack exchange,提问作者Stefano Martini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 17:58:03