Explain Regex.replace with a transform lambda. How does it differ from string-replacement, and what do $1/${name} mean in the string form?
answer
- Lambda: replace(input){ mr -> ... } returns verbatim
- String form: $1 / ${name} / $0 substitution
- No $-expansion in lambda result
- replaceFirst for first match only
- Returns new String (immutable)
basics
~10 sreplace can take a lambda that receives each MatchResult and returns the replacement text, so you compute it dynamically. The string form instead uses $1 or ${name} to insert captured groups.
solid answer
~40 sRegex.replace has two overloads. The string form replace(input, replacement: String) substitutes every match, and in that replacement string $1, $2 (or ${name}) are back-references to captured groups, while $0 is the whole match — to output a literal dollar or backslash you escape with a backslash. The lambda form replace(input) { matchResult -> String } gives full control: for each MatchResult you can read groupValues/groups, run arbitrary Kotlin, and return any String (no $-substitution happens in the lambda's return value). Use the lambda when the replacement depends on the matched content (e.g. uppercasing, arithmetic, lookups); use the string form for simple structural rewrites. There's also replaceFirst for only the first match. Both return a new String — Kotlin strings are immutable, so the original is untouched.
code
kotlin · 7 lines// dynamic replacement via lambda
val masked = Regex("\\d{4}").replace("card 1234 5678") { "*".repeat(it.value.length) }
// "card **** ****"
// group reordering via string form
val swapped = Regex("(?<d>\\d{2})/(?<m>\\d{2})").replace("23/06", "\${m}-\${d}")
// "06-23"go deeper
Knows replace exists and can do a simple string replacement.
Uses the lambda overload to compute replacements and reads $1/${name} in the string form.
Chooses the right overload, understands no $-substitution in the lambda, and handles escaping/immutability correctly.
Considers injection/escaping safety of user-supplied replacement text and favors the lambda form to eliminate substitution-token risks; reasons about performance over large inputs.
## Two replace overloads ### 1. String replacement (with substitution syntax) ```kotlin fun replace(input: CharSequence, replacement: String): String ``` In the `replacement` string, special tokens expand: - `$1`, `$2`, ... — the text of capturing group 1, 2, ... - `${name}` — a named group's text. - `$0` — the entire match. - To emit a literal `$` or `\`, escape it with a backslash inside the replacement. ```kotlin Regex("(\\w+)@(\\w+)").replace("a@b", "$2.$1") // "b.a" ``` ### 2. Transform lambda ```kotlin fun replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String ``` For each match you get the `MatchResult` and return the replacement. **No `$`-substitution is applied to the lambda's result** — the returned string is used verbatim — so you have arbitrary Kotlin at your disposal: ```kotlin val shout = Regex("\\w+").replace("keep it quiet") { it.value.uppercase() } // "KEEP IT QUIET" val bumped = Regex("\\d+").replace("v1 v2") { (it.value.toInt() + 1).toString() } // "v2 v3" ``` ## When to use which - **String form**: simple, declarative reordering/wrapping of captured groups; fast to read. - **Lambda form**: replacement value depends on computation, external lookups, conditionals, or per-match formatting. ## Related and important notes - **`replaceFirst(input, replacement)`** replaces only the first match. - All return a **new** `String`; Kotlin `String` is immutable, so the input is never mutated. - Watch the `$`/`\` escaping in the string form — an unescaped `$` followed by a digit you didn't intend is a classic bug; the lambda form sidesteps escaping entirely, which is why it's safer for user-derived replacement text.
- Does the lambda's returned string undergo $1 substitution?No. The lambda result is used literally; $-back-references only apply to the String replacement overload.
- How do you insert a literal $ using the String replacement form?Escape it with a backslash in the replacement string so it isn't read as a group back-reference.
saying these in an interview costs you the question
- Expecting $1 to work inside the lambda's return value
- Forgetting replace returns a new String (thinking it mutates)
- Not escaping $ in the string-replacement form
- Using string form for replacements that need computation
- Confusing replace (all matches) with replaceFirst