Регулярные выражения в Kotlin с примерами: на практике
Регулярные выражения (regex) — мощный инструмент для работы с текстом, позволяющий выполнять поиск, замену и валидацию строк по шаблону. В Kotlin работа с регулярными выражениями реализована через класс Regex и набор удобных функций-расширений. В этой статье мы разберем синтаксис, основные методы и рассмотрим практические примеры, которые помогут вам быстро освоить regex в Kotlin.
1. Основы работы с классом Regex
В Kotlin регулярное выражение создается с помощью класса Regex. Шаблон можно задать строкой или с помощью raw-строки (тройные кавычки """), что особенно удобно, чтобы не экранировать обратные слеши.
// Обычная строка
val pattern1 = Regex("\\d+") // одна или более цифр
// Raw-строка (рекомендуется)
val pattern2 = Regex("""\d+""") // то же самое, но без экранирования
Класс Regex также принимает необязательные флаги, например, RegexOption.IGNORE_CASE для регистронезависимого поиска.
val caseInsensitive = Regex("""hello""", RegexOption.IGNORE_CASE)
2. Основные методы: match, find, replace
Kotlin предоставляет несколько ключевых методов для работы с регулярными выражениями. Рассмотрим самые популярные.
2.1. Метод matchEntire (полное совпадение)
Проверяет, соответствует ли вся строка шаблону. Возвращает MatchResult? или null.
val regex = Regex("""\d{3}-\d{2}-\d{4}""")
val text = "123-45-6789"
val matchResult = regex.matchEntire(text)
println(matchResult?.value) // Вывод: 123-45-6789
// Если строка не соответствует шаблону
val badText = "123-45-678"
println(regex.matchEntire(badText)) // Вывод: null
2.2. Метод find (первое совпадение)
Ищет первое вхождение шаблона в строке. Возвращает MatchResult?.
val regex = Regex("""\d+""")
val text = "Цена: 150 рублей, скидка: 30%"
val firstMatch = regex.find(text)
println(firstMatch?.value) // Вывод: 150
2.3. Метод findAll (все совпадения)
Находит все непересекающиеся вхождения шаблона. Возвращает последовательность MatchResult.
val regex = Regex("""\d+""")
val text = "Цена: 150 рублей, скидка: 30%"
val allMatches = regex.findAll(text)
allMatches.forEach { println(it.value) }
// Вывод:
// 150
// 30
2.4. Метод replace (замена)
Заменяет все вхождения шаблона на указанную строку или результат лямбды.
val regex = Regex("""\d+""")
val text = "ID: 12345, код: 67890"
val result = regex.replace(text, "***")
println(result) // Вывод: ID: ***, код: ***
// Замена с использованием лямбды (динамическая замена)
val dynamicResult = regex.replace(text) { matchResult ->
"[" + matchResult.value.toInt().toString() + "]"
}
println(dynamicResult) // Вывод: ID: [12345], код: [67890]
3. Группы захвата (capturing groups)
Группы захвата позволяют извлекать части совпадения. В Kotlin к группам можно обращаться по индексу или имени (если задано).
3.1. Доступ по индексу
val regex = Regex("""(\d{2})\.(\d{2})\.(\d{4})""") // дата в формате ДД.ММ.ГГГГ
val text = "Сегодня: 15.03.2024"
val match = regex.find(text)
if (match != null) {
val (day, month, year) = match.destructured
println("День: $day, Месяц: $month, Год: $year")
// Вывод: День: 15, Месяц: 03, Год: 2024
}
3.2. Именованные группы
В Kotlin можно использовать именованные группы (синтаксис (?<name>...)).
val regex = Regex("""(?<username>\w+)@(?<domain>\w+\.\w+)""")
val text = "email: user@example.com"
val match = regex.find(text)
if (match != null) {
val username = match.groups["username"]?.value
val domain = match.groups["domain"]?.value
println("Имя пользователя: $username, Домен: $domain")
// Вывод: Имя пользователя: user, Домен: example.com
}
4. Практические примеры
Рассмотрим несколько реальных задач, которые часто встречаются при разработке на Kotlin.
4.1. Валидация email
fun isValidEmail(email: String): Boolean {
val emailRegex = Regex("""^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$""")
return emailRegex.matches(email)
}
println(isValidEmail("test@example.com")) // true
println(isValidEmail("invalid-email")) // false
4.2. Извлечение всех URL из текста
fun extractUrls(text: String): List<String> {
val urlRegex = Regex("""https?://[^\s]+""")
return urlRegex.findAll(text).map { it.value }.toList()
}
val text = "Посетите сайт https://pythonlib.ru и https://kotlinlang.org"
val urls = extractUrls(text)
println(urls) // [https://pythonlib.ru, https://kotlinlang.org]
4.3. Замена дат в тексте
fun formatDates(text: String): String {
val dateRegex = Regex("""(\d{2})\.(\d{2})\.(\d{4})""")
return dateRegex.replace(text) { match ->
val (day, month, year) = match.destructured
"$year-$month-$day" // переводим в формат ISO
}
}
val text = "Дата: 15.03.2024, еще дата: 01.01.2025"
println(formatDates(text)) // Дата: 2024-03-15, еще дата: 2025-01-01