代码之家  ›  专栏  ›  技术社区  ›  Brandon Montgomery

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

  •  36
  • Brandon Montgomery  · 技术社区  · 16 年前

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

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

    …然后意识到这比我想象的要复杂(上面的正则表达式是 差一点

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

    • 3856变为3856
    • 398868483992变为398868483992

    11 回复  |  直到 16 年前
        1
  •  128
  •   Tim Pietzcker    8 年前

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

    寻找 (?<=\d)(?=(\d\d\d)+(?!\d)) 并用 ,

    在旧版本中,JavaScript不支持lookbehind,因此这不起作用。幸运的是,我们只需要改变一点点:

    寻找 (\d)(?=(\d\d\d)+(?!\d)) 并用 \1,

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

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

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

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

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

    然后像这样使用它:

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

    Mastering Regular Expressions, 3rd. edition

        2
  •  19
  •   Speednet    14 年前

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

    代码:

    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( "." );
        }
    };
    

        3
  •  4
  •   kennebec    16 年前

    //您可能需要考虑小数

    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=1000000000.34;

        4
  •  4
  •   Adam Leggett    6 年前

    有一个警告 Intl.NumberFormat Number.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))
        5
  •  3
  •   Rafi    5 年前
    function numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
    }
    var num=numberWithCommas(2000000); //any number
    console.log(num);
    
    enter code here
    

    试试这个

        6
  •  3
  •   mpen    5 年前

    underscore.string a nice implementation .

    我稍微修改了它以接受数字字符串。

    function numberFormat(number, dec, dsep, tsep) {
      if (isNaN(number) || number == null) return '';
    
      number = parseFloat(number).toFixed(~~dec);
      tsep = typeof tsep == 'string' ? tsep : ',';
    
      var parts = number.split('.'),
        fnums = parts[0],
        decimals = parts[1] ? (dsep || '.') + parts[1] : '';
    
      return fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + tsep) + decimals;
    }
    
    console.log(numberFormat(123456789))
    console.log(numberFormat(123456789.123456789))
    console.log(numberFormat(-123456789))
    console.log(numberFormat(1E6))
    console.log(numberFormat(1E-6))
    console.log('---')
    console.log(numberFormat(123456789, 6, ',', '_'))
    console.log(numberFormat(123456789.123456789, 6, ',', '_'))
    console.log(numberFormat(-123456789, 6, ',', '_'))
    console.log(numberFormat(1E6, 6, ',', '_'))
    console.log(numberFormat(1E-6, 6, ',', '_'))
        7
  •  1
  •   Jeff B    16 年前

    如果确实需要正则表达式,可以在while循环中使用两个:

    while(num.match(/\d{4}/)) {
        num = num.replace(/(\d{3})(,\d|$)/, ',$1$2');
    }
    

    如果你想成为一名花花公子,你也可以用小数点格式化数字:

    while(num.match(/\d{4}(\,|\.)/)) {
        num = num.replace(/(\d{3})(,\d|$|\.)/, ',$1$2');
    }
    

    编辑:

    您也可以使用2个正则表达式,而不使用循环、拆分、联接等:

    num = num.replace(/(\d{1,2}?)((\d{3})+)$/, "$1,$2");
    num = num.replace(/(\d{3})(?=\d)/g, "$1,");
    

    如果剩余的数字可以被三整除,则第一个正则表达式会在前1或2位后面加一个逗号。第二个正则表达式在剩下的每一组3位数字后面加一个逗号。

    测试输出:

    45
    3,856
    398,868,483,992
    
    635
    12,358,717,859,918,856
    -1,388,488,184
    
        8
  •  1
  •   Robusto    16 年前

    有人提到在Javascript RegExp中不可能使用lookbehind。这是一个很好的页面,解释了如何使用lookaround(向前看和向后看)。

    http://www.regular-expressions.info/lookaround.html

        9
  •  0
  •   Seth    16 年前

    试着这样做:

    function add_commas(numStr)
    {
        numStr += '';
        var x = numStr.split('.');
        var x1 = x[0];
        var x2 = x.length > 1 ? '.' + x[1] : '';
        var rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
        }
        return x1 + x2;
    }
    
        10
  •  0
  •   Ryan Brunner    16 年前

    我认为您必须通过多次传递才能使用正则表达式实现这一点。请尝试以下操作:

    1. 运行一个正则表达式,后跟3位数字。
    2. 重复此操作,直到(1)未找到匹配项。
        11
  •  0
  •   Justin Johnson    16 年前

    迭代是不必要的

    function formatNumber(n, separator) {
        separator = separator || ",";
    
        n = n.toString()
            .split("").reverse().join("")
            .replace(/(\d{3})/g, "$1" + separator)
            .split("").reverse().join("");
    
        // Strings that have a length that is a multiple of 3 will have a leading separator
        return n[0] == separator ? n.substr(1) : n;
    }
    
    var testCases = [1, 45, 2856, 398868483992];
    for ( var i in testCases ) {
        if ( !ns.hasOwnProperty(i) ) { continue; }
        console.info(testCases[i]);   
        console.log(formatNumber(testCases[i]));
    }
    

    结果

    1
    1
    
    45
    45
    
    2856
    2,856
    
    398868483992
    398,868,483,992
    
        12
  •  0
  •   Harmen    16 年前

    首先反转一个字符数组,然后在每三个数字后面添加逗号,除非它正好在字符串末尾或-符号之前。然后再次反转字符数组并使其再次成为字符串。

    function add_commas(numStr){
        return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join('');
    }
    
        13
  •  0
  •   Levi Beckman    12 年前

    布兰登,

    从小数点开始,我没有看到太多的答案在正则表达式中起作用,所以我想我可能会插话。

    function addCommas(inputText) {
        // pattern works from right to left
        var commaPattern = /(\d+)(\d{3})(\.\d*)*$/;
        var callback = function (match, p1, p2, p3) {
            return p1.replace(commaPattern, callback) + ',' + p2 + (p3 || '');
        };
        return inputText.replace(commaPattern, callback);
    }
    

    >> Fiddle Demo <<

        14
  •  0
  •   Bijendra Singh    6 年前

    经过这么多的搜索,我生成了一个接受所有格式的正则表达式