如何使用正则表达式同时为整数和小数插入指定格式的分隔逗号
问题描述
我查阅过大量仅支持纯整数或纯小数插入逗号分隔符的实现方案,但未找到可同时兼容两类数字的正则写法,因此在此提问。
需求为仅对数字的整数部分按规则插入逗号,小数部分保持原有内容不做处理,具体转换规则示例如下:
1234->1,2341234567->12,34,567123->1231234.123->1,234.1230.123->0.1230.12345->0.12345
我尝试编写了两个正则表达式,均无法同时兼容整数、小数场景,无法达到预期效果,测试无效的正则写法如下:
/(\d)(?=(\d{3})+)/ /\B(?=(\d{3})+(?!\d))\.?\d*/
请问应如何编写符合上述需求的正则表达式?
解决方案
首先说明:你给出的1234567 -> 12,34,567属于印度式数字分隔规则(从右往左首段3位,后续每2位一隔),其余示例符合通用千分位分隔规则,以下分别给出对应实现,两种实现均不会修改小数部分内容。
1. 通用千分位分隔实现(匹配除特殊7位示例外的所有规则)
可用正则如下:
/\B(?<!\.\d*)(?=(\d{3})+(?!\d))/g
规则说明
\B:匹配非单词边界,避免在数字最开头插入逗号(?<!\.\d*):负向后行断言,排除小数点后方的所有位置,保证小数部分不会被插入任何分隔符(?=(\d{3})+(?!\d)):正向先行断言,匹配位置后方连续有3的倍数个数字,且数字后没有其他数字(即到整数部分末尾或小数点位置),精准定位整数部分需要加逗号的位置
2. 印度式分隔实现(完全匹配你给出的所有示例)
调整预查规则即可,正则如下:
/\B(?<!\.\d*)(?=(\d{2})*\d{3}(?!\d))/g
兼容性降级方案(不支持正则后顾断言的环境可用)
如果运行环境不支持ES2018以上的负向后行断言(比如低版本IE),可以先拆分整数、小数部分,单独处理整数部分再拼接,逻辑更稳定:
const formatNumber = (num) => { const [intPart, decPart] = String(num).split('.') // 千分位用这个 const formattedInt = intPart.replace(/\B(?=(\d{3})+(?!\d))/g, ',') // 印度式替换成下面这行即可 // const formattedInt = intPart.replace(/\B(?=(\d{2})*\d{3}(?!\d))/g, ',') return decPart ? `${formattedInt}.${decPart}` : formattedInt } // 测试用例 console.log(formatNumber(1234)) // 千分位输出1,234 / 印度式输出1,234 console.log(formatNumber(1234567)) // 千分位输出1,234,567 / 印度式输出12,34,567 console.log(formatNumber(123)) // 输出123 console.log(formatNumber(1234.123)) // 千分位输出1,234.123 / 印度式输出1,234.123 console.log(formatNumber(0.123)) // 输出0.123 console.log(formatNumber(0.12345)) // 输出0.12345
内容的提问来源于stack exchange,提问作者Pytan
相关产品推荐
相关产品推荐

