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

保龄球得分匹配Regex问题:后行断言与重复捕获组应用

嘿,我来帮你搞定保龄球得分的正则匹配问题!你遇到的重复捕获组只抓最后一次的问题,其实是正则引擎的固有特性,咱们换个思路就能解决,还能拆成JSON子模式方便维护,一步步来:

保龄球得分匹配与计算的正则方案(JSON结构)

核心问题拆解

首先得明确:你之前碰到的重复捕获组只保留最后一次结果是正则的常规操作——当你用(...)重复匹配时,引擎只会存储最后一次匹配的内容。所以要获取所有10帧的得分,不能靠单个重复捕获组,得把每帧的模式明确拆分,同时单独处理第10帧的特殊规则(因为第10帧允许额外击球,直接关联奖励球的数量)。

第一步:拆分正则子模式(JSON结构)

我们可以把不同的符号规则拆成独立的子模式,方便维护和组合,JSON结构如下:

{
  "subPatterns": {
    "miss": "-",
    "digit": "[0-9]",
    "strike": "X",
    "spare": "(?<!X)(\\d|-)/",  // 补中不能以全中开头,用后行断言排除前面是X的情况
    "singleBall": "(?:X|\\d|-)",  // 单个有效击球:全中、数字、失误
    "frameNormal": "(?:X|(?:\\d|-)(?:\\d|-|/))",  // 前9帧的有效格式:要么全中,要么两个球(含补中)
    "frame10": "(?:X(?:X|\\d|-){0,2}|(?:\\d|-)/\\d|(?:\\d|-){2})",  // 第10帧的所有合法情况
    "rewardArea": "(?:\\|(?:X|\\d|-){0,2})?"  // 奖励区:根据第10帧情况匹配0-2个球
  },
  "fullPattern": "^(?:(?<frame>[X\\d-](?:[\\d-/]|(?<=X))\\|){9}(?<frame10>X(?:X\\d|-){0,2}|[\\d-]/[\\d-]|[\\d-]{2})\\|(?<reward>[X\\d-]{0,2})\\|)?$"
}

子模式细节说明

  • miss:匹配失误符号-
  • digit:匹配0-9的数字得分
  • strike:匹配全中X
  • spare:用后行断言(?<!X)确保补中前面不是全中(符合规则:补中只能是同一帧的第二个球)
  • singleBall:单个有效击球的统一模式,方便复用
  • frameNormal:前9帧的通用格式,要么一个全中,要么两个球(包含补中)
  • frame10:覆盖第10帧的三种合法场景:
    1. 全中后接0-2个额外球(对应奖励球规则)
    2. 补中后接1个额外球
    3. 普通的两个非全中/非补中的球
  • rewardArea:自动匹配奖励区,根据第10帧的结果对应0-2个球

第二步:解决分组捕获问题

要获取所有10帧的得分,我们可以给前9帧分别设置命名捕获组(避免重复组的坑),全量匹配正则如下:

^(?<frame1>X|[\d-][\d-/])\|
(?<frame2>X|[\d-][\d-/])\|
(?<frame3>X|[\d-][\d-/])\|
(?<frame4>X|[\d-][\d-/])\|
(?<frame5>X|[\d-][\d-/])\|
(?<frame6>X|[\d-][\d-/])\|
(?<frame7>X|[\d-][\d-/])\|
(?<frame8>X|[\d-][\d-/])\|
(?<frame9>X|[\d-][\d-/])\|
(?<frame10>X(?:X|[\d-]){0,2}|[\d-]/[\d-]|[\d-]{2})\|
(?<reward>[X\d-]{0,2})\|$

这个正则把前9帧分别用frame1到frame9命名捕获,第10帧用frame10,奖励区用reward,这样就能拿到每帧的具体内容,完美避开重复捕获组只存最后一次的问题。

第三步:通过匹配组推导总分的逻辑

拿到每个捕获组的内容后,按规则计算总分:

  1. 前9帧得分:
    • 全中X:得10分 + 下两球的得分(比如当前帧是X,取后面一帧的前两球,或第10帧的球)
    • 补中x/(比如5/):得10分 + 下一球的得分
    • 普通球(比如3-或45):直接相加数字(-算0分)
  2. 第10帧得分:
    • 全中:10分 + 两个奖励球的得分(如果有)
    • 补中:10分 + 一个奖励球的得分(如果有)
    • 普通球:直接相加数字
  3. 注意:奖励球仅用于计算前9帧的全中/补中加分,本身不单独计入总分

举个例子:完美比赛得分串X|X|X|X|X|X|X|X|X|XXX||

  • 前9帧每个全中都是10 + 后面两球的10+10,9*30=270
  • 第10帧三个全中得30分,总分300

补充:关于后行断言的使用

你之前用(?<!X)排除补中前面是全中的思路是对的,完全符合保龄球规则(补中不能接在全中后面)。在第10帧的模式里,我们已经把这种非法情况排除在外,所以整个正则只会匹配合法的得分格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:43:34