JavaScript正则表达式中带量词的捕获组丢失中间匹配值的问题
JavaScript正则表达式中带量词的捕获组丢失中间匹配值的问题
嘿,我最近在写HSL颜色格式的正则表达式时碰到了个头疼的问题——明明正则能正确匹配整个字符串,但中间的捕获组总是拿不到值,只能得到第一个和最后一个匹配结果。具体情况是这样的:
我的正则表达式是:
/^hsl\((\d+)(?:deg)?(?:[\s,]\s*(\d+)%?){2}\)$/
测试了几个案例:
hsl(0,1,2) // 匹配结果是 0, 2(预期应该是 0, 1, 2) hsl(123deg 456% 789%) // 匹配结果是 123, 789(预期是 123, 456, 789) hsl(360deg, 50%, 25%) // 匹配结果是 360, 25(预期是 360, 50, 25) hsl(532) // 匹配失败(这是预期的)
问题原因
其实核心问题很简单:当你给一个捕获组加上重复量词(比如这里的{2})时,每次重复匹配都会覆盖这个捕获组的内容。也就是说,你的第二个捕获组(\d+)在第一次匹配到1(或者456、50)的时候确实被捕获了,但紧接着第二次匹配到2(或者789、25)时,就把之前的值覆盖掉了,最后只留下最后一次匹配的结果。
解决方案
既然HSL格式固定是三个值(色相、饱和度、亮度),那我们可以把重复的部分拆成两个独立的非捕获组,每个里面包含一个捕获组,这样就能分别捕获中间和最后一个值了。修改后的正则如下:
/^hsl\((\d+)(?:deg)?(?:[\s,]\s*(\d+)%?)(?:[\s,]\s*(\d+)%?)\)$/
再测试之前的案例,就能得到预期的三个捕获值了:
hsl(0,1,2)→ 捕获到0, 1, 2hsl(123deg 456% 789%)→ 捕获到123, 456, 789hsl(360deg, 50%, 25%)→ 捕获到360, 50, 25
如果以后遇到需要捕获多个重复匹配项的场景(比如不确定数量的情况),可以用matchAll()方法配合循环来获取所有捕获结果,不过这个场景下拆分组是最直接高效的方式。
备注:内容来源于stack exchange,提问作者Julian Brooks
相关产品推荐
相关产品推荐

