24

Does Kotlin have support for named regex groups?

Named regex group looks like this: (?<name>...)

gs_vlad
  • 1,409
  • 4
  • 15
  • 29

6 Answers6

31

According to this discussion,

This will be supported in Kotlin 1.1. https://youtrack.jetbrains.com/issue/KT-12753

Kotlin 1.1 EAP is already available to try.


"""(\w+?)(?<num>\d+)""".toRegex().matchEntire("area51")!!.groups["num"]!!.value

You'll have to use kotlin-stdlib-jre8.

Vadzim
  • 24,954
  • 11
  • 143
  • 151
7

As of Kotlin 1.0 the Regex class doesn't provide a way to access matched named groups in MatchGroupCollection because the Standard Library can only employ regex api available in JDK6, that doesn't have support for named groups either.

If you target JDK8 you can use java.util.regex.Pattern and java.util.regex.Matcher classes. The latter provides group method to get the result of named-capturing group match.

Ilya
  • 21,871
  • 8
  • 73
  • 92
3

As of Kotlin 1.4, you need to cast result of groups to MatchNamedGroupCollection:

val groups = """(\w+?)(?<num>\d+)""".toRegex().matchEntire("area51")!!.groups as? MatchNamedGroupCollection 
if (groups != null) {
    println(groups.get("num")?.value)
}

And as @Vadzim correctly noticed, you must use kotlin-stdlib-jdk8 instead of kotlin-stdlib:

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
}

Here is a good explanation about it

Dmitrii Bocharov
  • 872
  • 6
  • 21
1

The above answers did not work for me, what did work however was using the following method:

val pattern = Pattern.compile("""(\w+?)(?<num>\d+)""")
val matcher = pattern.matcher("area51")

while (matcher.find()) {
    val result = matcher.group("num")
}
Robin
  • 704
  • 8
  • 24
0

kotlin

fun regex(regex: Regex, input: String, group: String): String {
    return regex
        .matchEntire(input)!!
        .groups[group]!!
        .value
}

@Test
fun regex() {
    // given
    val expected = "s3://asdf/qwer"

    val pattern = "[\\s\\S]*Location\\s+(?<s3>[\\w/:_-]+)[\\s\\S]*"
    val input = """
        ...
        ...
        Location    s3://asdf/qwer
        Serde Library    org.apache.hadoop.hive.ql.io.orc.OrcSerde
        InputFormat    org.apache.hadoop.hive.ql.io.orc.OrcInputFormat
        OutputFormat    org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat
    """.trimIndent()
    val group = "s3"

    // when
    val actual = CommonUtil.regex(pattern.toRegex(), input, group)

    // then
    assertEquals(expected, actual)
}
seunggabi
  • 1,699
  • 12
  • 12
0

In Kotlin 1.9+, named groups are now available in the common stdlib:

As of Kotlin 1.8.0, the standard library is compiled with JVM target 1.8. So in 1.9.0, there is now a common groups function that you can use to retrieve a group's contents by its name for a regular expression match. This is useful when you want to access the results of regular expression matches belonging to a particular capture group.

What's new in Kotlin 1.9.0 (emphasis original)

They provide a nice example:

fun main() {
    val regex = """\b(?<city>[A-Za-z\s]+),\s(?<state>[A-Z]{2}):\s(?<areaCode>[0-9]{3})\b""".toRegex()
    val input = "Coordinates: Austin, TX: 123"

    val match = regex.find(input)!!
    println(match.groups["city"]?.value)
    // Austin
    println(match.groups["state"]?.value)
    // TX
    println(match.groups["areaCode"]?.value)
    // 123
}
user3030010
  • 1,767
  • 14
  • 19