如何将一串数字格式化为逗号表千分位。找到一种使用正则表达的方法,一直不太明白。花了点时间将匹配过程记录下来。由于理解能力较差,其中的"$1"着实烧脑了一阵子。有些结论是我测试的结果,可能有些偏差,请大家斧正。
我们先从例子入手:将“1234567890”输出为“1,234,567,890"
javascript代码:
let strTemp = '1234567890'.replace(/(\d)(?=(\d{3})+$)/g, '$1,')
大家可以试试,看到了吧,就是这么简单,下面分解一下为什么会得到正确的结果。正则表达式为
(\d)(?=(\d{3})+$)
里面使用到了下面的元素:
描述 | 表达式 |
---|---|
捕获模式 | (表达式) |
正向预查模式 | (?=表达式) |
匹配 n次 | {n} |
匹配 1 次或多次 | + |
最少 m 次,最多 n 次匹配 | {m,n} |
字符串结尾 | $ |
匹配数字 | \d |
分解一下:
(\d{3})+$,是从结尾重复匹配连续的3个数字
在此例中等价于 (\d{3}){1,3}$
1234567890 输出 1234567890,相当于234 567 890这三组数字一起输出,如果改成
(\d{3}){1,1}$
1234567890 输出 1234567890
(\d{3}){1,2}$
1234567890 输出 1234567890
下一步,重点来了,使用正向预查模式(?=表达式),输出表达式”(\d{3})+$“之前的部分
(?=(\d{3})+$)
1234567890 输出三个空位置,用"x"表示 1x234x567x890
现在懞圈了吧,为什么输出三个x呢?
因为”+"为匹配 1 次或多次,而(?=表达式)匹配一次就输出一次,
第一次匹配"890"就输出“x890"前的x
第二次匹配"567890"就输出“x567890"前的x
第三次匹配"234567890"就输出“x234567890"前的x。
没有第四次,因为再向前匹配只有一个数字1,条件不满足了。
好了,下面只需将所有"x"代替为",“就行了。可是"x"仅仅是几个空位置,可视化不强,所以再做一点变形加上”(\d)“,表示为匹配正向预查结果之前的一个数字,分别为1,4,7
(\d)(?=(\d{3})+$)
1234567890 输出 1234567890
最后用上面的JS语句将"1”,“4”,“7"替换为"1,”,“4,”,“7,”,就可输出正确结果。
到现在为止没有跟"$1"扯上任何关系,各位不慌,下面继续展开。
let strTemp = '1234567890'.replace(/(\d)(?=(\d{3})+$)/g, '$1,')
上面的”$1“是个什么鬼呢,它表示捕获模式下从左向右第一个(表达式)的匹配结果,此例中”$1“是(\d),这没什么可说的,我要说的是下面这个表达式中”$1“表示什么
(?=(\d{3})+$)
经过我测试,正向预查模式”(?=表达式)“的输出不是”$1“,
所以就是它了
(\d{3})+$
但是问题来了,你不是说这个会输出三个,分别是”890“,”567890“,”234567890“,到底是哪一个?
经过测试它只输出第一次匹配,也就是”890“
结论是在匹配 1 次或多次"+“表达式中,虽然结果只是输出最长的匹配,”$1"根据匹配方向不同,结果也不同
(\d{3})+ 或 ^(\d{3})+
1234567890 输出 1234567890,“$1"保留最后一次匹配结果"789”
(\d{3})+$
1234567890 输出 1234567890,“$1"保留第一次匹配结果"890”
而(\d{3})就比较奇怪了,"$1"似乎有三个结果”123“,”456“,”789“,目前还未有合理的解释。