繁体   English   中英

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

[英]Regular Expression for formatting numbers in JavaScript

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

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

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

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

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

……你懂的。

这可以在单个正则表达式中完成,不需要迭代。 如果您的浏览器支持 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

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

此代码扩展了 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( "." );
    }
};

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

// 您可能需要考虑小数

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

需要注意的是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))

function numberWithCommas(x) {
    return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
var num=numberWithCommas(2000000); //any number
console.log(num);

enter code here

试试这个

underscore.string一个很好的实现

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

 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, ',', '_'))

尝试这样的事情:

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;
}

如果你真的想要一个正则表达式,你可以在一个 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,");

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

这些不适用于小数,但它们适用于正整数和负整数。

测试输出:

45
3,856
398,868,483,992

635
12,358,717,859,918,856
-1,388,488,184

有人提到在 Javascript RegExp 中不可能进行后视。 这是一个很棒的页面,解释了如何使用环视(前瞻和后视)。

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

整数和小数的一个 RegExp:

// Formats number 1234.5678 into string "1 234.5678".
function formatNumber(number: number): string {
    return number.toString().replace(/(?<!(\.\d*|^.{0}))(?=(\d{3})+(?!\d))/g, ' ');
}

console.log(formatNumber(1234.5678)); // "1 234.5678"
console.log(formatNumber(123)); // "123"
console.log(formatNumber(123.45678)); // "123.45678"
console.log(formatNumber(123456789.11111111)); // "123 456 789.1111111"

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

  1. 运行一位数字后跟 3 位数字的正则表达式。
  2. 如果该正则表达式匹配,则将其替换为第一位数字,然后是逗号,然后是接下来的 3 位数字。
  3. 重复直到 (1) 找不到匹配项。

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

function add_commas(numStr){
    return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join('');
}

迭代不是必需的

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

布兰登,

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

我想知道重写正则表达式以从后向前扫描是否有任何优雅的好处......

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);
}

>> 小提琴演示 <<

这占任何小数位。

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

(\\d+[-, ,(]{0,3}\\d+[-, ,(,)]{0,3}\\d+[-, ,(,)]{0,3}\\d+[)]{ 0,2})

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM