You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中如何获取正则表达式重复分组的所有匹配结果?

SVG路径表达式解析:正则匹配重复分组的解决方案

我需要解析SVG <path> 元素中的路径表达式,方便在JavaScript里对点做变换。一开始尝试用正则表达式解析(代码如下),但结果不符合预期——只能捕获每个重复分组的最后一次出现。想知道怎么实现预期效果?能不能只用正则表达式完成?如果JS正则只能这样,我会考虑先用正则初步匹配,再用常规JS完成剩余解析,但先想了解有没有其他基于正则的方案,同时也想更好掌握正则的用法。

let path = `M4,24
    L4,23
    Q12,23,12, 9
    L14, 9
    C15, 3,25, 3,26,9
    L28,9
    Q28,23,36,23
    L36,24
    Z`

// 此函数无法正常工作
function parsePath(path) {
    // 为简化正则匹配,先处理路径字符串:
    // 将所有逗号和空白字符替换为单个空格分隔符
    let path2 = path.replaceAll(/[,\s]+/g, ' ')
    let rgx = /([A-Za-z])(?:(\d+)\s+)*/g
    
    let matches = [...path2.matchAll(rgx)].map(x => {
        return [x[1], x.slice(2)] 
    })

    return matches
}

console.log(parsePath(path));
// 实际输出:
[
  [ 'M', [ '24' ] ],
  [ 'L', [ '23' ] ],
  [ 'Q', [ '9' ] ],
  [ 'L', [ '9' ] ],
  [ 'C', [ '9' ] ],
  [ 'L', [ '9' ] ],
  [ 'Q', [ '23' ] ],
  [ 'L', [ '24' ] ],
  [ 'Z', [ undefined ] ]
]
// 预期输出:
[
  [ 'M', [ '4', '24' ] ],
  [ 'L', [ '4', '23' ] ],
  [ 'Q', [ '12', '23', '12', '9' ] ],
  // ...
]

问题原因

JavaScript正则中的重复捕获组只会保留最后一次匹配的结果,之前的匹配内容会被覆盖。你写的正则(?:(\d+)\s+)*里,(\d+)每次匹配数字都会更新捕获组的内容,最终只留下最后一个数字,这就是为什么实际输出里每个命令只拿到最后一个数值。

解决方案

由于JS正则本身不支持直接捕获重复分组的所有匹配结果,更实用的方式是分两步处理:

方案:拆分命令+提取数字

  1. 先把路径字符串标准化,统一用空格分隔所有元素
  2. 用正则匹配每个命令(字母)和对应的所有数字片段
  3. 把每个数字片段拆分成单独的数值数组

修改后的代码如下:

function parsePath(path) {
    // 标准化路径:逗号/空白替换为单个空格,去除首尾空格
    const normalizedPath = path.replace(/[,\s]+/g, ' ').trim();
    // 匹配每个命令:字母 + 后续所有数字(空格分隔)
    const commandRegex = /([A-Za-z])([\d\s]*)/g;
    const result = [];
    
    let match;
    while ((match = commandRegex.exec(normalizedPath)) !== null) {
        const [, command, numStr] = match;
        // 拆分数字串,过滤空值(避免首尾空格导致的空元素)
        const numbers = numStr.trim().split(/\s+/).filter(Boolean);
        result.push([command, numbers]);
    }
    
    return result;
}

// 测试输出
console.log(parsePath(path));

执行后会得到符合预期的结果:

[
  [ 'M', [ '4', '24' ] ],
  [ 'L', [ '4', '23' ] ],
  [ 'Q', [ '12', '23', '12', '9' ] ],
  [ 'L', [ '14', '9' ] ],
  [ 'C', [ '15', '3', '25', '3', '26', '9' ] ],
  [ 'L', [ '28', '9' ] ],
  [ 'Q', [ '28', '23', '36', '23' ] ],
  [ 'L', [ '36', '24' ] ],
  [ 'Z', [] ]
]

补充说明

如果想针对不同SVG命令的数字数量(比如M/L需要2个数字,Q需要4个,C需要6个)做更严格的校验,可以在拆分数字后根据命令类型做处理,但上面的方案已经能满足基础的解析需求。

内容的提问来源于stack exchange,提问作者PizzaOverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 21:05:16