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

解析PokerStars手牌历史的awk脚本循环变量覆盖、输出错位问题

问题根因

1. 记录分隔符配置与实际文本格式不匹配

脚本中设置的RS="\n\r\n\r\n\r\n"搞反了换行符和回车符的顺序。Windows平台导出的PokerStars手牌,每行结尾是标准的\r\n(先回车回到行首,再换行到下一行),两个手牌之间的三个空行对应的实际分隔串是\r\n\r\n\r\n。因为分隔符配置错误,awk无法正确拆分独立的手牌记录,第一份手牌的开头标识行根本没被归入对应记录的处理范围,直接导致第一条记录的元数据(手牌ID、游戏类型、时间)全部为空。

2. 残留回车符导致输出错位

脚本用FS="\n"拆分每条记录的行时,拆出来的每一行末尾都带着Windows格式的\r(回车符)。这个字符在终端输出时会强制把光标移回当前行的最开头,后续打印的内容会直接覆盖行首的已有文本——你看到的「字段拼接重叠、内容串到上一行」的错位输出,本质就是这个回车符造成的,和用print还是printf没有关系。

3. 全局变量无重置造成值串扰

awk的变量默认是全局生命周期,如果不主动在每条记录处理前把临时提取的变量(handID/gameType/dateTime/holeCards)重置为空值,一旦某条记录没匹配到对应的标识行,上一条记录残留的旧值就会被带出来,进一步加剧字段错位。

4. split字段索引计算错位

用空格作为split分隔符时,awk会自动把连续的多个空白符合并为一个分隔边界,脚本中写的数组索引(比如aHand[3]、aHand[5]等)完全没对应上实际拆分后的数组位置,既漏了游戏类型里的Hold'em部分,也经常提取不到正确的字段值。

修复方案
  1. 将RS改成兼容多平台换行的正则形式,不管是\r\n还是\n格式的分隔都能正确识别
  2. 每条记录处理的最开头,先重置所有临时提取变量,避免跨记录的值串扰
  3. 逐行清理行尾的\r字符,从根源解决输出错位问题
  4. 用正则匹配的方式直接从行文本里提取目标字段,不再逐个数split的空格位置,避免文本格式微调就失效
修复后可直接运行的脚本示例
BEGIN{
  # 兼容Windows/Unix格式的三空行记录分隔
  RS="\r?\n\r?\n\r?\n"
  FS="\n"
  OFS=","
  print "Hand ID,Game Type,Time,Holecards"
}
{
  # 每条记录处理前先重置所有临时变量,避免值串扰
  handID = gameType = dateTime = holeCards = ""
  for (i = 1; i <= NF; i++){
    # 清理每一行末尾的多余回车符
    sub(/\r$/, "", $i)
    # 匹配手牌开头行,提取手牌ID、游戏类型、时间
    if (match($i, /^PokerStars Hand #([0-9]+):\s+(.+) - ([0-9\/]+ [0-9:]+ ET)$/, matchRes)){
      handID = "#" matchRes[1] ":"
      gameType = matchRes[2]
      dateTime = matchRes[3]
    }
    # 匹配自己的底牌行
    if (match($i, /^Dealt to me \[(.+)\]$/, matchCard)){
      holeCards = "[" matchCard[1] "]"
    }
  }
  print(handID, gameType, dateTime, holeCards)
}

注:上述脚本基于Gawk 5.1及以上版本编写,如果使用的旧版gawk不支持match函数的第三参数,可以手动用substr截取对应位置的内容,核心逻辑保持一致即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 02:15:04