两个正则搞定数字增加千分符
原创
2019-4-26
11:31
编辑于
2022-6-17
15:35
使用 Number 原生方法可以轻松实现。
但是也存在问题,比如上图中的第二个和第三个数只保留了三位小数,原来 toLocaleString 小数超过三位会四舍五入,所以如果你没有多位小数顾虑,那么可以直接使用,否则只能寻找别的方法了。另外 toLocaleString 是很早就有的内置方法,不用担心兼容性问题。
之前在网上找到一个目前来讲最简洁有效方法,两个正则就搞定。
function addThousandSeparator(num) {
return num.toString().replace(/^(-?)(\d+)(\.?\d*)$/, function(num, minus, integer, decimal) {
return minus + integer.replace(/\B(?=(\d{3})+(?!\d))/g, ',') + decimal
})
}
下面分析下这两个正则是如何搞定的。
第一个正则^(-?)(\d+)(\.?\d*)$
分析:
- 匹配一个数字,包括负数
- 将数字各个部分用括号分组
- 符号第一组
- 整数第二组
- 小数部分是第三组,
?
匹配0或1个,\d*
表示匹配0个或更多
第一个正则没啥难度,第二个正则才是核心。一般在第一个正则的基础上对第二组整数部分用字符串截取的方式也可以搞定,但是如果用一个正则就可以搞定,逼格一下子就上来了。
第二个正则/\B(?=(\d{3})+(?!\d))/
分析:
\B
匹配不是单词开头或结束的位置,要区分小位置和匹配内容,简单说位置可以理解为字符前后的缝隙,比如常用的^$
分别是匹配字符串开始和结束的位置(?=exp)
匹配exp前面的位置(?!exp)
匹配后面跟的不是exp的位置(\d{3})+(?!\d)
匹配的是一个或更多组三个数字,但是数字后面的位置的后面不能是数字,也就是说多组三个数字的后面不是数字才满足匹配(?=(\d{3})+(?!\d))
匹配的是上面的(多组三个数字且后面不是数字)的前面的位置
下面用一个实例更加直观的讲述上面的匹配过程,以数字 123456789 为例。
- 字符串的开头的位置满足要求(1前面的位子),因为后面刚好是3组3个数字,而且数字最后面的位置是字符串结束的位置(位置后面不是数字),但是 \B 表示不能匹配开头的位置,因此这里又不满足需求,这也是 \B 加在前面的原因,防止刚好数字的位数是3的倍数的情况
- 由于加了 /g 全局搜索,需要继续往后搜索,接着 3 和 4 中间的位置也满足要求,后面是2组3个数字
- 接着 6 和 7 的中间的位置也满足要求,后面是1组3个数字
使用 match 方法,可以看到匹配了三个空字符串也就是三个位置。
关注我的公众号