正则表达式插入逗号
问题描述: 给定一个字符串,要求在字符串中的每个数字之间插入一个逗号。 示例: 输入:"1234567890" 输出:"1,234,567,890" 解决方案:
javascript
function insertCommas(str) {
return str.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
解析: 这个正则表达式 /(?=(\d{3})+$)/g
的目的是在数字字符串中从右向左每三位添加一个逗号(千位分隔符)。以下是执行逻辑的详细分析:
正则表达式分解:
(?=...)
正向先行断言(positive lookahead)。它匹配一个位置(不消耗字符),要求这个位置之后的内容必须满足...
的条件。(\d{3})+$
\d{3}
:匹配连续三个数字。(\d{3})+
:匹配一个或多个连续的三个数字分组。$
:匹配字符串的结尾。- 整体要求:从当前位置到字符串结尾,数字的长度必须是 3 的倍数。
g
标志
全局匹配,找到所有符合条件的位置。
执行逻辑步骤(以 "100000000000"
为例):
原始字符串:
"100000000000"
(长度 12,是 3 的倍数)。匹配位置:
- 引擎从左向右扫描,检查每个位置是否满足条件:从该位置到结尾的数字长度是 3 的倍数。
- 匹配的位置:
- 位置
0
:后面 12 位数字(100000000000
),长度 12 是 3 的倍数。 - 位置
3
:后面 9 位数字(000000000
),长度 9 是 3 的倍数。 - 位置
6
:后面 6 位数字(000000
),长度 6 是 3 的倍数。 - 位置
9
:后面 3 位数字(000
),长度 3 是 3 的倍数。
- 位置
- 共匹配 4 个位置:
0
、3
、6
、9
。
替换操作:
- 在每个匹配的位置插入逗号
,
。 - 插入后:
- 位置
0
插入 →",100000000000"
- 位置
3
插入 →",100,000000000"
- 位置
6
插入 →",100,000,000000"
- 位置
9
插入 →",100,000,000,000"
- 位置
- 在每个匹配的位置插入逗号
为什么输出是 "100,000,000,000"
而不是 ",100,000,000,000"
?
- 关键点:在位置
0
插入逗号后,字符串变为",100000000000"
。但后续匹配的位置3
、6
、9
是基于原始字符串的索引(不是新字符串)。 - 插入逗号后,原始字符串的索引会向后偏移:
- 在位置
0
插入逗号后,新字符串中:- 原始索引
0
的字符'1'
移动到新索引1
。 - 原始索引
3
的字符'0'
移动到新索引4
。
- 原始索引
- 引擎继续使用原始索引,在原始索引
3
插入逗号时,实际插入到新字符串的索引4
(即'1'
后的位置),形成"100,"
。
- 在位置
- 最终结果:位置
0
的逗号被后续字符覆盖,只保留"100,000,000,000"
。
验证逻辑:
字符串
"123456"
(长度 6):- 匹配位置:
0
(后面 6 位)和3
(后面 3 位)。 - 输出:
"123,456"
(位置0
的逗号被覆盖,位置3
的逗号保留)。
- 匹配位置:
字符串
"12345"
(长度 5):- 匹配位置:
2
(后面"345"
长度 3)。 - 输出:
"12,345"
。
- 匹配位置:
潜在问题:
- 开头逗号问题:如果字符串长度是 3 的倍数,位置
0
会匹配,但实际输出中开头逗号会被覆盖(如上述逻辑)。若字符串不以数字开头(如负号),可能暴露问题。 - 更健壮的方案:常见写法是
/(\d)(?=(\d{3})+$)/g
,替换为'$1,'
。它匹配一个数字(后跟三的倍数位),避免位置0
:javascript"100000000000".replace(/(\d)(?=(\d{3})+$)/g, '$1,') // 输出 "100,000,000,000"
总结:
- 逻辑:匹配所有从该位置到结尾的数字长度是 3 的倍数的位置,插入逗号。
- 实际效果:从右向左每三位加逗号,位置
0
的逗号会被覆盖,因此输出正确。 - 适用场景:纯数字字符串,长度可能不是 3 的倍数(如长度 5 时匹配位置
2
)。