Python如何解析PGN字符串:筛选以数字加点开头的棋步行存入列表
思路可行性判断
你提出的「遍历PGN拆分列表,识别以1-2位数字加英文句点开头的行作为棋步内容」的核心逻辑完全可行,这个判断规则完全贴合标准PGN格式规范:
- 所有PGN元数据行均以方括号
[开头,不会以数字加句点的格式开头 - 用来做格式分隔的空行没有有效内容
- 只有连续承载棋步的文本行,才会以“回合数+英文句点”的格式作为行首
但你写的示例代码存在几个需要修正的问题:
str.startswith()方法仅支持匹配固定字符串,无法直接实现“1位/2位数字+句点”的模糊匹配。如果硬用这个方法实现,需要把所有可能的回合数字字符串全部列举出来,维护成本极高- 列表追加的语法写错了:正确的追加写法是
列表.append(元素),你示例里写的列表[元素]是列表索引访问的语法,运行会直接触发报错 - 没有覆盖棋步行末尾带对局胜负标记(如
1-0、0-1、1/2-1/2)的情况,直接提取的话会把多余的结果标记混入棋步内容,和你预期的输出不符
优化后的实现方案
针对上述问题,用正则表达式实现匹配逻辑会更简洁可靠,完整可运行的示例代码如下:
import re # 示例输入的PGN拆分列表 pgn = [ '[ECO "B08"]', '', '1.e4 d6 2.d4 Nf6 3.Nc3 g6 4.Nf3 Bg7 5.Be2 Nbd7 6.O-O O-O 7.e5 dxe5 8.dxe5 Ng4', '9.e6 Nde5 10.Qxd8 Rxd8 11.Nxe5 Nxe5 12.Nb5 c6 13.Nc7 Rb8 14.f4 Ng4 15.Bxg4 Bd4+', '16.Kh1 Bb6 17.f5 Bxc7 18.fxg6 fxg6 19.Bh6 Be5 20.Rad1 Rxd1 21.Rxd1 Bd6 22.Rf1 1-0', '', '[Event "Telechess ol1 7778"]', ] listmove = [] # 匹配行首为1-3位数字+英文句点的棋步行 move_line_check = re.compile(r'^\d{1,3}\.') # 匹配行末尾的对局结果标记 result_clean = re.compile(r'\s*(1-0|0-1|1/2-1/2|\*)\s*$') for line in pgn: # 跳过无内容的空行 if not line.strip(): continue # 判断当前行是否为棋步内容行 if move_line_check.match(line): # 清除行末尾的多余结果标记 cleaned_content = result_clean.sub('', line).strip() listmove.append(cleaned_content) # 按照预期格式拼接所有棋步行 final_moves = ','.join(listmove) print(final_moves)
运行上述代码的输出和你给出的预期内容完全一致。
几个实现细节说明:
- 正则匹配的范围设置为
\d{1,3},覆盖了所有现实对局的回合数范围(即使是超长对局也不会超过三位数),比固定写1-2位数字的适用场景更广 - 清洗规则只会删除行尾的对局结果标记,不会改动棋步内部的内容,保证棋步本身的完整性
- 整个逻辑不需要依赖第三方PGN解析库,对初学者来说实现门槛很低,完全契合当前的学习需求
内容的提问来源于stack exchange,提问作者Trojan666
相关产品推荐
相关产品推荐

