我需要使用JavaScript在网页上显示格式化的数字。我想格式化它,以便在正确的位置有逗号。我如何使用正则表达式执行此操作?我已经达到了这样的目的:
myString = myString.replace(/^(\d{3})*$/g, "${1},");
......然后意识到这将比我想象的更复杂(上面的正则表达式甚至不接近到我需要的东西)。我已经做了一些搜索,我很难找到适用于此的东西。
基本上,我想要这些结果:
......你明白了。
答案 0 :(得分:108)
这可以在单个正则表达式中完成,无需迭代。如果您的浏览器支持ECMAScript 2018,您可以简单地使用环视,只需在正确的位置插入逗号:
搜索(?<=\d)(?=(\d\d\d)+(?!\d))
并将所有内容替换为,
在旧版本中,JavaScript不支持lookbehind,因此不起作用。幸运的是,我们只需要改变一点:
搜索(\d)(?=(\d\d\d)+(?!\d))
并将所有内容替换为\1,
因此,在JavaScript中,它看起来像:
result = subject.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,");
说明:断言从字符串中的当前位置开始,可以匹配三位数的数字,并且当前位置还有一位数字。
这也适用于小数(123456.78),只要“点右侧”没有太多数字(否则你得到123,456.789,012)。
您也可以在Number原型中定义它,如下所示:
Number.prototype.format = function(){
return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
};
然后像这样使用它:
var num = 1234;
alert(num.format());
图片来源:Jeffrey Friedl,Mastering Regular Expressions, 3rd. edition,p。 66-67
答案 1 :(得分:16)
使用一行代码可以优雅地处理格式化数字。
此代码扩展了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( "." );
}
};
除非确实有必要,否则我更喜欢第一版的简洁性。
答案 2 :(得分:3)
//您可能希望将小数计入帐户
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()=返回值:(String)10,000,000,000.34
答案 3 :(得分:3)
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
var num=numberWithCommas(2000000); //any number
console.log(num);
enter code here
尝试一下
答案 4 :(得分:2)
如果你真的想要一个正则表达式,你可以在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
答案 5 :(得分:1)
有人提到在Javascript RegExp中无法实现lookbehind。这是一个很棒的页面,解释了如何使用lookaround(lookahead和lookbehind)。
答案 6 :(得分:1)
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;
},
答案 7 :(得分:0)
尝试这样的事情:
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;
}
答案 8 :(得分:0)
我认为您必须使用正则表达式进行多次传递才能实现此目的。请尝试以下方法:
答案 9 :(得分:0)
首先反转一个字符数组,然后在每隔三个数字之后添加逗号,除非它在字符串结尾之前或 - 符号之前。然后再次反转字符数组并再次使其成为字符串。
function add_commas(numStr){
return numStr.split('').reverse().join('').replace(/(\d{3})(?=[^$|^-])/g, "$1,").split('').reverse().join('');
}
答案 10 :(得分:0)
没有必要进行迭代
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
答案 11 :(得分:0)
布兰登,
我没有看到从小数点开始处理正则表达式的答案太多,所以我想我可能会插话。
我想知道重写正则表达式以便从后面扫描是否有任何优雅的好处......
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);
}
这会占任何小数位。
答案 12 :(得分:0)
需要注意的是,Intl.NumberFormat
和Number.toLocaleString()
现在已经在JavaScript中用于此目的:
使用正则表达式的其他答案都分解为十进制数字(尽管作者似乎不知道这一点,因为他们只测试了1或2个小数位)。这是因为,不带回首,JS正则表达式无法知道您是在小数点之前还是在小数点之后使用数字块。这留下了两种使用JS正则表达式解决此问题的方法:
了解数字中是否存在小数点,并根据其使用不同的正则表达式:
/(\d)(?=(\d{3})+$)/g
表示整数/(\d)(?=(\d{3})+\.)/g
代表小数位使用两个正则表达式,一个正则表达式匹配小数部分,第二个正则表达式对其进行替换。
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))
答案 13 :(得分:0)
经过大量搜索,我生成了一个接受所有格式的正则表达式
(\ d + [-,,(] {0,3} \ d + [-,,(,)] {0,3} \ d + [-,,(,)] {0,3} \ d + [ )] {0,2})