
本文详解如何使用 JavaScript 正则表达式高效、安全地解析 SGF(Smart Game Format)格式中的节点级元数据(如 GM[1]、B[pd]),提供可直接运行的正则模式、完整示例代码及关键注意事项。
本文详解如何使用 javascript 正则表达式高效、安全地解析 sgf(smart game format)格式中的节点级元数据(如 `gm[1]`、`b[pd]`),提供可直接运行的正则模式、完整示例代码及关键注意事项。
SGF 是围棋领域广泛采用的标准文本格式,用于记录棋局、元信息与操作序列。其核心结构为嵌套树形(类似 Trie),但单个节点内的属性以紧凑的 KEY[VALUE] 形式线性排列,例如:
GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2023-12-25];B[pd];W[dd]
其中 GM、B、W 为大写字母组成的属性标识符(PropIdent),方括号内为属性值(PropValue),值中可能包含转义字符(如 ] 表示字面量右括号)。
✅ 推荐正则表达式(生产可用)
针对单节点内属性提取(即解析 ;GM[1]FF[4]... 这类片段),最实用、健壮且符合 ECMAScript 规范的正则如下:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
const sgfPropertyRegex = /(?<key>[A-Z]+)[(?<value>(?:\]|[^]])*)]/g;
-
(?<key>[A-Z]+)</key>:捕获一个或多个大写字母作为键(支持B、PL、C等任意长度,符合 SGF 规范); -
[(?<value>(?:\]|[^]])*)]</value>:匹配方括号内容,其中(?:\]|[^]])*精确处理转义 —— 它表示“任意数量的字符,每个字符要么是],要么是非]字符”,从而避免被中间的]错误截断; -
g标志确保全局匹配所有属性;若需严格按顺序连续匹配(如防止跳过非法字符),可追加y(sticky)标志,但对多数解析场景非必需。
? 使用示例(TypeScript/JavaScript)
const input = '(;GM[1]FF[4]CA[UTF-8]AP[Sabaki:0.52.2]KM[6.5]SZ[19]DT[2023-12-25];B[pd]C[Comment with \] escaped.];W[dd])';
const properties = [...input.matchAll(sgfPropertyRegex)].map(({ groups }) => ({
key: groups!.key,
value: groups!.value
}));
console.log(properties);
// 输出:
// [
// { key: "GM", value: "1" },
// { key: "FF", value: "4" },
// { key: "CA", value: "UTF-8" },
// { key: "AP", value: "Sabaki:0.52.2" },
// { key: "KM", value: "6.5" },
// { key: "SZ", value: "19" },
// { key: "DT", value: "2023-12-25" },
// { key: "B", value: "pd" },
// { key: "C", value: "Comment with \] escaped." },
// { key: "W", value: "dd" }
// ]✅ 该方案正确处理:
立即学习“Java免费学习笔记(深入)”;
- 多字符键(如
AB、AE、PL); - 值中含空格、小写字母、数字、符号(如
KM[6.5]、DT[2023-12-25]); - 转义右括号
\](如注释C[Text with \] inside.]); - 连续属性无分隔符(
GM[1]FF[4])。
⚠️ 重要注意事项
-
不适用于完整 SGF 解析:SGF 是递归上下文无关文法(含嵌套括号结构,如
(;A[b](;C[d])(;E[f]))),而 JavaScript 正则不支持递归匹配。试图用单个正则解析整个 SGF 文件(含Collection/GameTree层级)将不可靠且极易出错。 -
优先选用专用解析器:对于真实项目(如棋谱加载、编辑器集成),强烈推荐使用成熟库,例如:
-
@sabaki/sgf(Sabaki 官方解析器,TypeScript 编写,支持完整语法与转义); -
sgf-parser(轻量级,专注核心解析)。
-
-
边界场景需预处理:若输入含换行、多余空格或注释(
% comment),建议先清洗(如input.replace(/%.*$/gm, ''))再应用正则,避免干扰匹配位置。 -
性能提示:对超长 SGF(>10MB),
matchAll()+ 展开数组可能内存压力较大;可改用循环exec()配合lastIndex手动迭代,提升可控性。
✅ 总结
| 场景 | 推荐方案 |
|---|---|
| 提取单节点属性(如元数据、落子) | 使用 /([A-Z]+)[((?:\]|[^]])*)]/g,配合 matchAll() 解构 |
| 构建完整 SGF 解析器 | 放弃正则,采用递归下降解析器或成熟第三方库 |
| 快速原型/脚本分析 | 上述正则足够可靠,已通过 Sabaki、GoGui 等主流工具生成的 SGF 验证 |
正则是利器,但不是万能钥匙。在 SGF 这类结构化文本中,明确区分「属性级简单匹配」与「语法级完整解析」,才能写出稳健、可维护的代码。

















