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

Angular TypeScript数字千分位格式化:规避Sonar正则性能警告及疑问

数字格式化解决方案(规避正则回溯风险)

一、Sonar警告的合理性

这个警告是合理的。如果你的原始正则包含嵌套量词、可选分支或无限制重复匹配,处理超长数字字符串时会触发大量回溯,导致CPU占用急剧升高,确实存在潜在的拒绝服务(DoS)风险——比如输入上百位的数字,低效正则可能会花费数秒甚至更久处理。

二、不使用正则的实现方案

手动处理整数部分的分组和开头零的去除,完全规避正则风险,逻辑清晰可控:

function formatNumber(num: number | string): string {
  // 统一转为字符串并去除首尾空白
  const numStr = typeof num === 'number' ? num.toString() : num.trim();
  // 拆分整数与小数部分
  let [integerPart, decimalPart = ''] = numStr.split('.');

  // 移除开头多余的零(全零则保留一个)
  let cleanedInteger = '';
  let leadingZeroPassed = false;
  for (const char of integerPart) {
    if (char === '0' && !leadingZeroPassed) {
      continue;
    }
    leadingZeroPassed = true;
    cleanedInteger += char;
  }
  cleanedInteger = cleanedInteger || '0';

  // 从后往前每三位添加空格分隔
  let formattedInteger = '';
  for (let i = cleanedInteger.length - 1, count = 0; i >= 0; i--) {
    formattedInteger = cleanedInteger[i] + formattedInteger;
    count++;
    if (count % 3 === 0 && i !== 0) {
      formattedInteger = ' ' + formattedInteger;
    }
  }

  // 补全小数部分到三位,不足补零
  const formattedDecimal = decimalPart.padEnd(3, '0').slice(0, 3);

  return `${formattedInteger},${formattedDecimal}`;
}

测试用例:

  • formatNumber(1234) → "1 234,000"
  • formatNumber('000123456') → "123 456,000"
  • formatNumber(789.12) → "789,120"
  • formatNumber(0) → "0,000"

三、修复正则以消除Sonar警告

如果一定要保留正则实现,需优化表达式避免回溯风险,核心是使用高效的正向预查逻辑,确保匹配过程线性执行:

function formatNumberWithOptimizedRegex(num: number | string): string {
  const numStr = typeof num === 'number' ? num.toString() : num.trim();
  let [integerPart, decimalPart = ''] = numStr.split('.');

  // 移除开头多余的零:仅匹配开头连续的零(后面跟有效数字),替换为空
  integerPart = integerPart.replace(/^0+(?=\d)/, '') || '0';

  // 三位分组:用\B确保不在开头加空格,正向预查匹配末尾前的三位分组
  const formattedInteger = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, ' ');

  // 补全小数部分
  const formattedDecimal = decimalPart.padEnd(3, '0').slice(0, 3);

  return `${formattedInteger},${formattedDecimal}`;
}

这个优化后的正则\B(?=(\d{3})+(?!\d))不会触发回溯,Sonar的静态分析会识别这种低风险写法,不再抛出警告。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:32:35