Does Kotlin have support for named regex groups?
Named regex group looks like this: (?<name>...)
Does Kotlin have support for named regex groups?
Named regex group looks like this: (?<name>...)
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
.
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.
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
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")
}
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)
}
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
}