Kotlin正则:如何从MatchResult中获取命名分组名称
解决Kotlin中MatchResult获取触发匹配的命名分组问题
Kotlin的MatchResult确实没有直接提供获取触发匹配的分组名称的属性,但可以通过正则表达式的namedGroups结合遍历检查来实现。你的正则是分支结构(|分隔),每次匹配只会命中其中一个命名分组,因此可以遍历所有命名分组,找到当前匹配中存在有效值的那个分组名称。
修改后的代码
val name = "my name@some-value" val regex = """(?<word>\p{L}+)|(?<sep>[^\p{L}]+)""".toRegex() val matchResults = regex.findAll(name) matchResults.forEach { match -> // 遍历所有命名分组,找到当前匹配中有效的那个 val matchedGroupName = regex.namedGroups.keys.first { match.group(it) != null } println("'${match.value}' is a $matchedGroupName") }
代码说明
- 获取正则的命名分组集合:通过
regex.namedGroups可以拿到所有定义的命名分组(这里是word和sep)。 - 找到触发匹配的分组:遍历分组名称,用
match.group(it) != null判断该分组是否在当前匹配中有有效值。由于你的正则是二选一的分支结构,每次匹配只会有一个分组满足条件,因此用first()直接取第一个符合条件的分组名称即可。 - 保留匹配顺序:
findAll()返回的匹配结果本身就是按输入字符串的匹配顺序排列的,完全满足你后续调用map{}处理并重构语句的需求。
扩展:分组处理与语句重构
如果需要对单词和分隔符分别处理后重构语句,可以这样做:
val processed = matchResults.map { match -> val groupName = regex.namedGroups.keys.first { match.group(it) != null } when (groupName) { "word" -> match.value.uppercase() // 处理单词,比如转大写 "sep" -> match.value // 分隔符保持原样 else -> match.value } }.joinToString("") println(processed) // 输出:MY NAME@SOME-VALUE
内容的提问来源于stack exchange,提问作者Rolf
相关产品推荐
相关产品推荐

