Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use back references in kotlin regular expressions?

Tags:

regex

kotlin

I'm trying to use a regular expression with back references in kotlin to replace the placeholders of a String in the following fashion:

Source: "This is a %s with %02d whatever"

Target: "This is a <s/> with <02d/> whatever"

So I'm looking for something like this but with a proper syntax, of course:

private fun escapePlaceHolders(text: String): String {
    return """%([^ ]+?)""".toRegex().replace(text, "<\1/>")
}

Obviously this code doesn't even compile, let alone work. The problem is that I do not know how to use the back reference in the replace function, if it can be done at all.

like image 983
Fran Marzoa Avatar asked Dec 10 '22 04:12

Fran Marzoa


1 Answers

You may use

val text = "This is a %s with %02d whatever"
val rx = """%(\d*[a-z])""".toRegex()
println(text.replace(rx, "<$1/>")) // => This is a <s/> with <02d/> whatever

If you need to perform extra actions on the group value before replacing, aka "pass the backreference to a function" (e.g. to upper- or lowercase the value), you can use an overload of the .replace method with the transform argument:

// To get the same result as above, i.e. wrap Group 1 with < >:
println(rx.replace(text) { "<${it.groupValues[1].uppercase()}>" })
// =>  This is a <S> with <02D> whatever
// If you just want to turn Group 1 value to upper case:
println(rx.replace(text) { it.groupValues[1].uppercase() })
// => This is a S with 02D whatever

See the Kotlin demo #1 and Kotlin demo #2.

Details

  • % - a % char
  • (\d*[a-z]) - Group 1 (later referred to with $1 from the replacement pattern):
    • \d* - 0+ digits
    • [a-z] - a lowercase ASCII letter.

Feel free to adjust the pattern to your input, the idea remains the same.

like image 51
Wiktor Stribiżew Avatar answered Mar 08 '23 03:03

Wiktor Stribiżew