JavaScript - 捕获重复组

JavaScript - Capture repeated group

提问人:Robert S 提问时间:6/28/2021 更新时间:6/28/2021 访问量:171

问:

使用 JavaScript(或 VBScript) 是否可以从 %n:32+5000 中单独捕获以下组?

  • 捕获组 1:%n
  • 捕获组 2::32
  • 捕获组 3:+5000

我尝试通过这个论坛搜索有关捕获重复组的信息,但给出的示例要么是使用不同的语言,如 .NET,要么提问者没有具体询问如何做我需要的事情。

到目前为止,我所做的最好的尝试是打开全局。此外,我正在使用 https://regex101.com/r/qBylQX/1 来帮助我可视化正在发生的事情;但是,到目前为止,我还没有破解它。(%n)(([:\+]\d+){0,2})

笔记:

  • 每个 %n 只允许一个实例
  • 每场比赛只允许 :\d+ 出现一次
  • 每场比赛只允许出现一次 +\d+。
  • 该模式可以出现在字符串中的任何位置。
JavaScript 正则表达式

评论


答:

1赞 Ryszard Czech 6/28/2021 #1

(%n)(?:(:\d+)(\+\d+)?)?

请参阅正则表达式证明

解释

--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    %n                       '%n'
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  (?:                      group, but do not capture (optional
                           (matching the most amount possible)):
--------------------------------------------------------------------------------
    (                        group and capture to \2:
--------------------------------------------------------------------------------
      :                        ':'
--------------------------------------------------------------------------------
      \d+                      digits (0-9) (1 or more times
                               (matching the most amount possible))
--------------------------------------------------------------------------------
    )                        end of \2
--------------------------------------------------------------------------------
    (                        group and capture to \3 (optional
                             (matching the most amount possible)):
--------------------------------------------------------------------------------
      \+                       '+'
--------------------------------------------------------------------------------
      \d+                      digits (0-9) (1 or more times
                               (matching the most amount possible))
--------------------------------------------------------------------------------
    )?                       end of \3 (NOTE: because you are using a
                             quantifier on this capture, only the
                             LAST repetition of the captured pattern
                             will be stored in \3)
--------------------------------------------------------------------------------
  )?                       end of grouping
0赞 The fourth bird 6/28/2021 #2

使用此模式还可以匹配 2 次或 2 次,因为 和 都在字符类中。(%n)(([:\+]\d+){0,2}):\d++\d+:+

重复捕获组 like 将仅捕获组中最后一次迭代的值。([:\+]\d+){0,2}

由于此重复位于外部捕获组 2 内,因此组 2 值将包含整个匹配项,并且您所追求的组中没有很好的值分离。


根据注释,其中任何一个只能出现一次,可以在比赛中出现。

如果要匹配 and 的两个组合,但如果它们不能相同,则可以使用带有反向引用的捕获组。:+

这些值位于组 1、3 和 4 中。

(%n)(?:([:+])(\d+)(?:(?!\2)([:+]\d+))?)?(?!\S)

模式匹配:

  • (%n)捕获组 1,匹配%n
  • (?:非捕获组作为一个整体进行匹配
    • ([:+])捕获组 2,匹配或:+
    • (\d+)捕获组 3,匹配 1+ 位数字
    • (?:非捕获组作为一个整体进行匹配
      • (?!\2)否定前瞻,断言右边的值与第 2 组中捕获的值不同
      • ([:+]\d+)捕获组 4、匹配或:+
    • )?关闭组并使其成为可选
  • )?关闭组并使其成为可选
  • (?!\S)在右侧断言空格边界以防止部分匹配

正则表达式演示

const regex = /(%n)(?:([:+])(\d+)(?:(?!\2)([:+]\d+))?)?(?!\S)/;
[
  "%n:32+5000",
  "%n:32",
  "%n+5000",
  "%n",
  "%n+32:5000",
  "%n+32",
  "%n:5000",
  "%n:32:5000",
  "%n+32+5000"
].forEach(s => console.log(`${regex.test(s)} ==> ${s}`));