如何捕获重复捕获组中每个组的组号

问题描述 投票:1回答:1

我的正则表达式是类似**(A)(([+-]\d{1,2}[YMD])*)**的东西,它与预期的匹配,例如A + 3M,A-3Y + 5M + 3D等。

但是我想捕获此子模式的所有组**([+-]\d{1,2}[YMD])***对于以下示例A-3M + 2D,我只能看到4个组。 A-3M+2D (group 0), A(group 1), -3M+2D (group 2), +2D (group 3)

有没有一种方法可以将**-3M**作为一个单独的组?

regex kotlin
1个回答
0
投票

通常重复捕获组capture only the last iteration。 Kotlin和Java均是如此,因为这些语言没有任何方法可以跟踪每个捕获组堆栈。

您可以采取的解决方法是,首先对整个字符串与字符串应匹配的特定模式进行验证,然后将字符串提取或分割成多个部分。

对于当前方案,您可以使用

val text = "A-3M+2D" 
if (text.matches("""A(?:[+-]\d{1,2}[YMD])*""".toRegex())) {
  val results =  text.split("(?=[-+])".toRegex())
  println(results)
}
// => [A, -3M, +2D]

请参见Kotlin demo

这里,

  • [text.matches("""A(?:[+-]\d{1,2}[YMD])*""".toRegex())确保整个字符串与A匹配,然后出现0个或多个+-,1或2位数字,后跟YMD
  • [.split("(?=[-+])".toRegex())-+之前,用空字符串分割文本。

图案详细信息

  • [^-隐含在.matches()中-字符串开头
  • [A-一个A子字符串
  • (?:-non-capturing group的开头:
    • [[+-]-匹配character class+-
    • [\d{1,2}-一位到两位数字
    • [YMD]-与YMD匹配的字符类>
  • [)*-非捕获组的结尾,重复0次或多次(由于[C​​0]量词)]
  • [*-隐含在\z中-字符串结尾。
  • [分割时,我们只需要查找matches()-之前的位置,因此我们使用正数+lookahead,它与紧随其后的位置(?=[-+])+相匹配。这是一种非消耗模式,匹配的-+不会添加到匹配值中。

具有单个正则表达式的另一种方法

您还可以使用基于-的正则表达式在字符串的开头首先检查字符串格式,并且只有在成功的情况下才开始匹配连续的子字符串:

\G

请参见val regex = """(?:\G(?!^)[+-]|^(?=A(?:[+-]\d{1,2}[YMD])*$))[^-+]+""".toRegex() println(regex.findAll("A-3M+2D").map{it.value}.toList()) // => [A, -3M, +2D] another Kotlin demo

详细信息

  • regex demo-先前成功匹配的结尾,然后是字符串的(?:\G(?!^)[+-]|^(?=A(?:[+-]\d{1,2}[YMD])*$))+(请参阅-)或(\G(?!^)[+-]),其后是|,然后是0或更大出现A / +,1或2位数字,然后出现-YM直到字符串的末尾(请参阅D
  • ^(?=A(?:[+-]\d{1,2}[YMD])*$)-除[^-+]+-之外的1个或多个字符。我们不必在这里过分小心,因为前行在字符串开始时就完成了繁重的工作。
© www.soinside.com 2019 - 2024. All rights reserved.