KotlinRegex:如何在MatchResult中获取组名

gpnt7bae  于 2023-06-24  发布在  Kotlin
关注(0)|答案(1)|浏览(103)

我想将RegEx的MatchResults与命名组链接回组名称,以便我可以告诉哪个组导致了该匹配。
Kotlin代码示例:

val name = "my name@some-value"

        val matchResults = """(?<word>\p{L}+)|(?<sep>[^\p{L}]+)"""
                           .toRegex()
                           .findAll(name)

        matchResults.forEach {
            println("'${it.value}' is a ${it.groupname}}")
        }

上面代码的问题是它无法编译(MatchResult类中没有groupname)。我无法找到一种方法来获取导致特定MatchResult的组的名称。
我希望上面的代码生成以下输出:

'my' is a word
        ' ' is a sep
        'name' is a word
        '@' is a sep
        'some' is a word
        '-' is a sep
        'value' is a word

我希望结果保持与输入字符串相同的顺序,这样我就可以调用.map {},然后以不同的方式处理单词和分隔符,然后重新构建句子。
我正在使用Kotlin1.8.0,目标是JDK 11。我知道对于这种组合,RegEx库确实支持命名组,但是MatchResults不包含任何对命名组的引用。

kknvjkwl

kknvjkwl1#

我找不到一种方法将RegEx的匹配结果连接到导致匹配结果的命名组。我解决这个问题的方法是将正则表达式拆分成组,并进行额外的匹配以找到匹配的组:

// Named regex groups separately stored in a map:
    val typeRegexes = mapOf (
        "word" to """(?<word>\p{L}+)""".toRegex(),
        "separator" to """(?<sep>[^\p{L}]+)""".toRegex()
    )

    // Simple function to see which regex group matches (first match wins)
    fun getTypeOf(string:String) :String =
        typeRegexes.entries.firstOrNull {
           it.value.matches(string) 
        }?.key ?: "unknown"

    // Combine all regex groups into a single regex so we have a
    // stream of ordered matchresults
    val combinedRegex = typeRegexes.values
                            .map { it.pattern }
                            .joinToString("|").toRegex()

    // The value to test (as in the original question)
    val name = "my name@some-value"
    
    // All match results in the correct order
    val matchResults = combinedRegex.findAll(name)
    
    // For each match result, do a second match on each group to print the type:
    matchResults.forEach {
        println("'${it.value}' is a ${getTypeOf(it.value)}")
    }

如果有更好的方法,请分享您的答案,谢谢!

相关问题