我的正则表达式就是这样**(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**
成为一个独立的小组?
重复的捕获组通常仅捕获最后一次迭代。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演示
这里,
text.matches("""A(?:[+-]\d{1,2}[YMD])*""".toRegex())
确保整个字符串匹配A
,然后0或多次出现的+
或-
,1或2位数字用Y
,M
或D
.split("(?=[-+])".toRegex())
在-
或之前使用空字符串分割文本+
。图案细节
^
-隐式输入.matches()
-字符串开头A
-A
子串(?:
-一个非捕获组的开始:
[+-]
-一个字符类匹配+
或-
\d{1,2}
-一到两位数字[YMD]
-字符类匹配Y
或M
或D
)*
-非捕获组的结尾,重复0次或更多次(由于*
量词)\z
-隐式输入matches()
-字符串末尾。分割时,我们只需要查找-
或之前的位置+
,因此我们使用正向前行,(?=[-+])
该位置与紧跟在+
或之后的位置相匹配-
。这是一种非消耗模式,+
或-
匹配不添加到匹配值中。
单个正则表达式的另一种方法
您也可以使用\G
基于正则表达式的方法,首先在字符串的开头检查字符串格式,如果成功,则仅开始匹配连续的子字符串:
val regex = """(?:\G(?!^)[+-]|^(?=A(?:[+-]\d{1,2}[YMD])*$))[^-+]+""".toRegex()
println(regex.findAll("A-3M+2D").map{it.value}.toList())
// => [A, -3M, +2D]
细节
(?:\G(?!^)[+-]|^(?=A(?:[+-]\d{1,2}[YMD])*$))
-先前成功匹配的结尾,然后是字符串的+
或-
(请参阅\G(?!^)[+-]
)或(|
)A
,然后是+
/ -
,然后是0或多次出现的/ ,1或2位数字,然后是Y
,M
或D
直到字符串的结尾(请参阅^(?=A(?:[+-]\d{1,2}[YMD])*$)
)[^-+]+
- 1个以上字符比其他-
和+
。我们在这里不必太小心,因为在字符串开始时先行进行了繁重的工作。本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句