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

使用递归正则在JavaScript中解析SGF格式的技术问询

使用递归正则将SGF转换为JavaScript树形对象

问题背景

SGF是存储围棋对局的文本格式,本质为树形结构的文本编码。由于ECMAScript原生不支持递归正则,尝试XRegExp的matchRecursive函数未得到预期结果,以下是正确的递归正则实现方案。

核心思路

SGF的核心结构是嵌套括号对,递归处理的关键是精准匹配多层嵌套的括号内容。XRegExp的matchRecursive函数专为这类场景设计,之前未达预期大概率是参数配置或内容过滤逻辑有误。

实现步骤

  1. 剥离外层括号:先移除SGF字符串首尾的最外层括号,聚焦内部节点内容。
  2. 分割独立节点:利用matchRecursive匹配分号开头的节点,同时跳过嵌套括号内的内容,避免错误分割。
  3. 递归解析节点:对每个节点,提取属性键值对,再递归解析其嵌套的子节点,最终组装为JavaScript树形对象。

代码实现

const XRegExp = require('xregexp');

function parseSgf(sgfStr) {
    // 移除最外层括号
    const innerContent = sgfStr.replace(/^\((.*)\)$/, '$1');
    
    // 分割顶层节点:匹配分号开头的节点,忽略嵌套括号内的内容
    const topLevelNodes = XRegExp.matchRecursive(innerContent, '\\(', '\\)', 'g', { valueNames: ['text', 'open', 'text', 'close'] })
        .filter(item => item.value.startsWith(';') || item.name === 'text')
        .map(item => item.value.trim())
        .filter(Boolean);
    
    const parseSingleNode = (nodeStr) => {
        const node = { properties: {}, children: [] };
        
        // 提取节点属性(如B[aa])
        const propertyMatches = nodeStr.match(/([A-Za-z]+)\[([^\]]+)\]/g) || [];
        propertyMatches.forEach(prop => {
            const [key, value] = prop.match(/([A-Za-z]+)\[([^\]]+)\]/).slice(1);
            node.properties[key] = value;
        });
        
        // 提取子节点的嵌套括号内容
        const childNodeMatches = XRegExp.matchRecursive(nodeStr, '\\(', '\\)', 'g', { valueNames: ['text', 'open', 'text', 'close'] })
            .filter(item => item.name === 'text')
            .map(item => item.value.trim())
            .filter(Boolean);
        
        // 递归解析子节点
        node.children = childNodeMatches.map(child => parseSgf(`(${child})`));
        
        return node;
    };
    
    return topLevelNodes.map(node => parseSingleNode(node));
}

// 测试用例
const testSgf = '(;B[aa](;W[ab];B[ac])(;W[ad];B[ae]))';
console.log(JSON.stringify(parseSgf(testSgf), null, 2));

关键说明

  • matchRecursive的valueNames参数用于区分不同类型的匹配内容,通过过滤可以精准提取节点文本和嵌套子节点内容。
  • 递归函数parseSingleNode负责单个节点的属性解析和子节点递归处理,确保树形结构的正确生成。
  • 需注意过滤空字符串和无效内容,避免解析过程出现异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:47:18