JavaScript 中用于格式化数字的正则表达式

IT技术 javascript regex formatting
2021-03-18 17:33:04

我需要使用 JavaScript 在网页上显示一个格式化的数字。我想格式化它,以便在正确的位置有逗号。我将如何用正则表达式做到这一点?我已经得到了这样的东西:

myString = myString.replace(/^(\d{3})*$/g, "${1},");

...然后意识到这会比我想象的更复杂(上面的正则表达式甚至不接近我需要的)。我已经做了一些搜索,我很难找到适合这个的东西。

基本上,我想要这些结果:

  • 45 变成 45
  • 3856 变成 3,856
  • 398868483992 变成 398,868,483,992

……你懂的。

6个回答

这可以在单个正则表达式中完成,不需要迭代。如果您的浏览器支持 ECMAScript 2018,您可以简单地使用环视并在正确的位置插入逗号:

搜索(?<=\d)(?=(\d\d\d)+(?!\d))并全部替换为,

在旧版本中,JavaScript 不支持后视,因此不起作用。幸运的是,我们只需要稍微改变一下:

搜索(\d)(?=(\d\d\d)+(?!\d))并全部替换为\1,

所以,在 JavaScript 中,这看起来像:

result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");

说明:断言从字符串中的当前位置开始,可以匹配三的倍数的数字,并且当前位置还剩一个数字。

只要“点的右边”没有太多数字(否则你会得到 123,456.789,012),这也适用于小数 (123456.78)。

您还可以在 Number 原型中定义它,如下所示:

Number.prototype.format = function(){
   return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
};

然后像这样使用它:

var num = 1234;
alert(num.format());

图片来源:Jeffrey Friedl,掌握正则表达式,第 3 期。,第 66-67

忘了添加...如果您确实希望浮点数小于 1,则在进行替换之前添加一个条件以要求该数字大于 999(这比尝试提出更复杂的 RegExp 来解决更小的浮点数要好比 1 可能最终会变得非常低效)。
2021-04-26 17:33:04
@10basetom:我在回答的最后提到了这个限制;此外,添加该条件也无济于事-1000.123456仍然会被屠杀:)
2021-05-02 17:33:04
我知道这很旧,但result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");对我不起作用。我不得不toString()在你的原型示例中添加
2021-05-02 17:33:04
这太棒了,除非你进入花车: 0.1523234 -> 0.1,523,234
2021-05-05 17:33:04
话虽如此,仍然是救命稻草!
2021-05-19 17:33:04

可以用一行代码优雅地处理数字格式。

此代码扩展了 Number 对象;下面包括使用示例。

代码:

Number.prototype.format = function () {
    return this.toString().split( /(?=(?:\d{3})+(?:\.|$))/g ).join( "," );
};

怎么运行的

正则表达式使用前瞻来查找字符串中的位置,它的右侧唯一的是一个或多个三个数字的分组,直到遇到小数或字符串结尾。.split()被用来打破在那些点串入数组元素,然后将.join()合并的那些元件回字符串,用逗号分开。

在字符串中查找位置而不是匹配实际字符的概念对于拆分字符串而不删除任何字符很重要。

用法示例:

var n = 9817236578964235;
alert( n.format() );    // Displays "9,817,236,578,964,235"

n = 87345.87;
alert( n.format() );    // Displays "87,345.87"

当然,可以很容易地扩展或更改代码以处理区域设置问题。例如,这是一个新版本的代码,它自动检测区域设置并交换逗号和句点的使用。

本地化版本:

Number.prototype.format = function () {

    if ((1.1).toLocaleString().indexOf(".") >= 0) {
        return this.toString().split( /(?=(?:\d{3})+(?:\.|$))/g ).join( "," );
    }
    else {
        return this.toString().split( /(?=(?:\d{3})+(?:,|$))/g ).join( "." );
    }
};

除非真的有必要,否则我更喜欢第一个版本的简单性。

在 JavaScript 中扩展本机对象不是一个好习惯。当你扩展一个对象时,你修改了它的行为。最好将其编写为一个简单的函数或定义您自己的类,这样不会导致原始对象出现意外行为。
2021-04-23 17:33:04
对我来说完美的工作也适用于这个正则表达式: replace(/\B(?=(\d{3})+(?!\d))/g, ",");
2021-04-28 17:33:04
嗯,这是一个哲学和有争议的论点。好消息是,您可以轻松地使用我上面的答案中的代码并创建一个简单的函数,正如您所说的那样。
2021-05-04 17:33:04
像其他答案一样,这仅适用于整数。您的十进制示例没有足够的数字来表明它不起作用。
2021-05-20 17:33:04

// 您可能需要考虑小数

Number.prototype.commas= function(){
 var s= '', temp, 
 num= this.toString().split('.'), n=num[0];
 while(n.length> 3){
  temp= n.substring(n.length-3);
  s= ','+temp+s;
  n= n.slice(0, -3);
 }
 if(n) s= n+s;
 if(num[1]) s+='.'+num[1];
 return s;
}

var n = 10000000000.34;

n.commas() = 返回值:(字符串)10,000,000,000.34

这个非常大的函数是我们为什么要使用正则表达式的一个很好的例子。
2021-05-07 17:33:04

需要注意的是Intl.NumberFormatNumber.toLocaleString()现在在 JavaScript 中用于此目的:

使用正则表达式的其他答案都分解为十进制数(尽管作者似乎不知道这一点,因为他们只测试了 1 或 2 个小数位)。这是因为没有lookbehind,JS正则表达式无法知道您是在处理小数点之前还是之后的数字块。这留下了两种使用 JS 正则表达式解决这个问题的方法:

  1. 知道数字中是否有小数点,并根据它使用不同的正则表达式:

    • /(\d)(?=(\d{3})+$)/g 对于整数
    • /(\d)(?=(\d{3})+\.)/g 对于小数
  2. 使用两个正则表达式,一个匹配小数部分,第二个对其进行替换。

function format(num) {
  return num.toString().replace(/^[+-]?\d+/, function(int) {
    return int.replace(/(\d)(?=(\d{3})+$)/g, '$1,');
  });
}

console.log(format(332432432))
console.log(format(332432432.3432432))
console.log(format(-332432432))
console.log(format(1E6))
console.log(format(1E-6))

如果您没有背后的支持,这可能是最好的方法。当用于屏蔽输入字段时,您可以使用正则表达式运行第一遍以在所需的位置插入小数,然后通过此方法运行结果,您将获得完美的逗号分布,而无需使用小数。
2021-04-20 17:33:04
function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
var num=numberWithCommas(2000000); //any number
console.log(num);

enter code here

试试这个