kotlinintermediate

Regex — Match, Replace, and Extract

Use Kotlin regex for pattern matching: find, replace, named groups, and structured extraction.

kotlin
fun main() {
    // Basic matching
    val emailRegex = Regex("""[\w.+-]+@[\w-]+\.[\w.-]+""")
    println(emailRegex.matches("user@example.com"))  // true
    println(emailRegex.matches("not-an-email"))      // false

    // containsMatchIn
    val text = "Contact us at support@test.com or sales@test.com"
    println(emailRegex.containsMatchIn(text)) // true

    // Find first
    val first = emailRegex.find(text)
    println("First: ${first?.value}") // support@test.com

    // Find all
    val allEmails = emailRegex.findAll(text).map { it.value }.toList()
    println("All: $allEmails")

    // Named groups
    val urlRegex = Regex("""(?<protocol>https?)://(?<host>[\w.-]+)(?<path>/[\w/.-]*)""")
    val url = "https://api.example.com/v1/users"
    urlRegex.find(url)?.let { match ->
        println("Protocol: ${match.groups["protocol"]?.value}")
        println("Host: ${match.groups["host"]?.value}")
        println("Path: ${match.groups["path"]?.value}")
    }

    // Destructuring with groups
    val dateRegex = Regex("""(\d{4})-(\d{2})-(\d{2})""")
    val dateStr = "2024-03-15"
    val (year, month, day) = dateRegex.find(dateStr)!!.destructured
    println("Date: $day/$month/$year")

    // Replace
    val censored = Regex("""\b\w+@\w+\.\w+\b""")
        .replace(text) { "[REDACTED]" }
    println("Censored: $censored")

    // Replace with backreference
    val reformatted = dateRegex.replace(dateStr) { match ->
        val (y, m, d) = match.destructured
        "$d/$m/$y"
    }
    println("Reformatted: $reformatted")

    // Split
    val csv = "  Alice , Bob ,  Charlie  "
    val names = Regex("""\s*,\s*""").split(csv.trim())
    println("Names: $names")

    // Log parser
    val logRegex = Regex("""\[(?<level>\w+)]\s+(?<timestamp>[\d:.-]+)\s+(?<message>.+)""")
    val logs = listOf(
        "[INFO] 2024-03-15:10:30 Server started",
        "[ERROR] 2024-03-15:10:31 Connection failed",
        "[DEBUG] 2024-03-15:10:32 Processing request"
    )
    data class LogEntry(val level: String, val timestamp: String, val message: String)

    val entries = logs.mapNotNull { line ->
        logRegex.find(line)?.let { match ->
            LogEntry(
                match.groups["level"]!!.value,
                match.groups["timestamp"]!!.value,
                match.groups["message"]!!.value
            )
        }
    }
    entries.filter { it.level == "ERROR" }.forEach { println("⚠ ${it.message}") }

    // Validation
    val validators = mapOf(
        "phone" to Regex("""^\+?\d{10,15}$"""),
        "hex" to Regex("""^#[0-9a-fA-F]{6}$"""),
        "ipv4" to Regex("""^(\d{1,3}\.){3}\d{1,3}$""")
    )
    val testValues = mapOf("phone" to "+1234567890", "hex" to "#ff00aa", "ipv4" to "192.168.1.1")
    testValues.forEach { (type, value) ->
        println("$type '$value' valid: ${validators[type]?.matches(value)}")
    }
}

Use Cases

  • Log file parsing and analysis
  • Input validation patterns
  • Text extraction and transformation

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.