我正在寻找一个简短的代码,可以将逗号放入一组数字中,直到我来到this site。
代码:
function addCommas(nStr)
{
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
工作真的很棒。有这个例子的数字集:
addCommas('83475934.89');
将返回"83,475,934.89"
,但是当我阅读代码时,我希望它返回8,3,4,7,5,934.89
,但此网站会解释
\d+
与\d{3}
组合将匹配一组3个数字,前面跟着任意数量的数字。这使得搜索从右到左进行替换。
我很困惑。
这段代码如何从右到左阅读?另外,$1
和$2
的含义是什么?
答案 0 :(得分:14)
实际从右向左阅读。真正发生的是它重复应用(\d+)(\d{3})
模式(通过while循环)并替换,直到它不再匹配模式。换句话说:
迭代1:
x1 = 83475934.89
x1.replace((\d+)(\d{3}), '$1' + ',' + '$2');
x1 = 83475,934.89
迭代2:
x1 = 83475,934.89
x1.replace((\d+)(\d{3}), '$1' + ',' + '$2');
x1 = 83,475,934.89
迭代3:
x1 = 83,475,934.89
x1.replace((\d+)(\d{3}), '$1' + ',' + '$2');
// no match; end loop
修改强>
另外,$ 1和$ 2是什么意思?
这些分别是对匹配组(\d+)
和(\d{3})
的反向引用。
这是学习正则表达式实际工作方式的绝佳参考:
http://www.regular-expressions.info/quickstart.html
答案 1 :(得分:7)
它从右到左匹配,因为它使用贪婪模式匹配。这意味着它首先找到所有数字(\ d +),然后尝试找到\ d {3}。例如,在数字2421567.56中,它将首先匹配数字直到'。' - 2431567 - 然后向后工作以匹配正则表达式的下一部分中的下三个数字(567)。它在一个循环中执行此操作,在$ 1和$ 2变量之间添加逗号。
$表示在正则表达式中用括号形成的匹配组,例如(\ d +)= $ 1和(\ d {3})= $ 2。这样,它可以轻松地在它们之间添加字符。
在下一次迭代中,贪婪匹配在新创建的逗号处停止,并且继续直到它不匹配> 3位数。
答案 2 :(得分:3)
这个解释在同一页面上进一步说明
代码说明:代码开始将字符串分成两部分 如果有小数,则部分( nStr 和 nStrEnd )。正则表达式 用于 nStr 以添加逗号。然后添加 nStrEnd 。如果 字符串没有 nStrEnd 暂时删除,然后是常规 表达式将 10.0004 格式化为 10.0,004
正则表达式解释: \ d + 与 \ d {3} 结合使用 匹配一组3个数字,前面是任意数量的数字。这个 欺骗搜索从右到左替换。
$1
和$2
是正则表达式中捕获的组匹配。您可以在Regex Tutorial上阅读有关此主题的更多信息。
答案 3 :(得分:2)
代码从右到左阅读,它的作用是搜索最大的一行数字(\d+)
,然后是3位(\d{3})
。 $ 1和$ 2分别是最大的数字行和3位数。因此它将逗号放在它们之间,通过重复此过程,它可以通过这种方式解析它。
答案 4 :(得分:2)
我写了一个正则表达式,它在一次传递中做同样的事情:
/(?!\b)(\d{3}(?=(\d{3})*\b))/g
尝试使用例如开头的不同数字:
var num = '1234567890123456';
for(var i = 1; i <= num.length; i++)
{
console.log(num.slice(0, -i).replace(/(?!\b)(\d{3}(?=(\d{3})*\b))/g, ',$1'));
}
&#13;
我试着在这里分解它:
暂时忽略这一点 - 我会回过头来看。
<强>(?!\ b)中强>(\ d {3}(?=(\ d {3})* \ b))的
它仍然从左到右读取,试图捕获3位数的块。这是捕获组。
(?!\ b)中的(\ d {3} 强>(?=(\ d {3})* \ b)中的)强>
但是,在捕获组内部,它使用前瞻。
(?!\ B)(\ d {3}的(?= 强>(\ d {3})* \ B'B>))
前瞻查找锚定到数字末尾的3位数的任意倍数 - 终止边界。这会将捕获与数字的右端3 的倍数对齐。这意味着它也可以使用十进制数字(除非它们超过3个小数位,在这种情况下它也会在其中加入逗号。它不是完美的。)
(?!\ B)(\ d {3}(?= (\ d {3})* \ B'/ B>))
我遇到的问题是JavaScript不支持原子查找,因此,当数字有3位数的倍数时,它匹配前3位数字并在数字的最开头加上逗号。
你不能在3位数匹配之前匹配一个字符而不会丢掉重复,所以我不得不使用与字边界相匹配的负向前瞻。它与^
一开始就相反。
(?!\ b)中(\ d {3}(?=(\ d {3})* $))
从本质上讲,它可以防止表达式从字符串的开头匹配
哪个会不好。
答案 5 :(得分:0)
只是反转字符串
function addCommas(num_as_string) {
// convert into string
num_as_string+='';
if (num_as_string === "") {
return num_as_string;
}
/* add more test here*/
// split the integer part and decimal part
let [integer_part, decimal_part] = num_as_string.split('.');
if (decimal_part === undefined) {
decimal_part = '';
} else {
decimal_part = '.' + decimal_part;
}
return integer_part.split('').reverse().join('').match(/\d\d?\d?/g).reverse().map(v => v.split('').reverse().join('')).join(',') + decimal_part;
}
输出:
addCommas('83475934.89')
"83,475,934.89"
addCommas(83475934.89)
"83,475,934.89"
addCommas(83475934)
"83,475,934"