Регулярные выражения в Kotlin: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Регулярные выражения в Kotlin: от основ до продвинутых техник

Регулярные выражения (regex) — это мощный инструмент для поиска, извлечения и замены текста по шаблону. В Kotlin работа с регулярными выражениями реализована через класс Regex, который предоставляет богатый API для всех стандартных операций. В этой статье мы разберем синтаксис, основные функции и практические примеры использования регулярных выражений в Kotlin.

1. Создание и базовый синтаксис Regex в Kotlin

В Kotlin регулярное выражение создается с помощью класса Regex или через расширение .toRegex() для строк. Поддерживаются все стандартные метасимволы и квантификаторы.

Способы создания Regex:

// Способ 1: через конструктор
val regex = Regex("\\d{3}-\\d{2}-\\d{4}")

// Способ 2: через toRegex()
val pattern = "[a-z]+@[a-z]+\\.[a-z]+".toRegex()

// Способ 3: с опциями (регистронезависимый)
val caseInsensitive = Regex("kotlin", RegexOption.IGNORE_CASE)

Основные метасимволы и квантификаторы:

  • . — любой символ (кроме перевода строки)
  • \d — цифра (0-9)
  • \w — буква, цифра или подчеркивание
  • \s — пробельный символ
  • ^ — начало строки
  • $ — конец строки
  • * — 0 или более повторений
  • + — 1 или более повторений
  • ? — 0 или 1 повторение
  • {n,m} — от n до m повторений

2. Основные операции: поиск, проверка и извлечение

Класс Regex предоставляет несколько методов для работы с текстом. Рассмотрим самые важные из них.

Проверка соответствия (matches)

Метод matches() проверяет, соответствует ли вся строка шаблону полностью:

val phonePattern = Regex("\\+7\\d{10}")
println(phonePattern.matches("+79261234567")) // true
println(phonePattern.matches("+7926123456")) // false (9 цифр вместо 10)

Поиск первого совпадения (find)

Метод find() возвращает первое совпадение в виде объекта MatchResult?:

val text = "Контакты: email@test.com и support@domain.org"
val emailRegex = "[\\w.]+@[\\w.]+\\.[a-z]+".toRegex()
val match = emailRegex.find(text)
println(match?.value) // email@test.com
println(match?.range) // 10..23 (индексы начала и конца)

Поиск всех совпадений (findAll)

Для получения всех совпадений используйте findAll(), который возвращает последовательность Sequence<MatchResult>:

val allMatches = emailRegex.findAll(text)
allMatches.forEach { match ->
    println("Найдено: ${match.value} в позиции ${match.range.first}")
}
// Вывод:
// Найдено: email@test.com в позиции 10
// Найдено: support@domain.org в позиции 28

Проверка на наличие (containsMatchIn)

Метод containsMatchIn() возвращает Boolean — есть ли хотя бы одно совпадение:

val hasEmail = emailRegex.containsMatchIn(text)
println(hasEmail) // true

3. Замена и split с помощью Regex

Регулярные выражения отлично подходят для замены частей строки и разделения текста.

Замена первого совпадения (replaceFirst)

val original = "ID: 12345, код: 67890"
val digitRegex = "\\d+".toRegex()
val masked = digitRegex.replaceFirst(original, "***")
println(masked) // ID: ***, код: 67890

Замена всех совпадений (replace)

val censored = digitRegex.replace(original, "***")
println(censored) // ID: ***, код: ***

Замена с использованием лямбды

Вы можете передать лямбду, которая будет вызываться для каждого совпадения:

val text = "Цены: 100р, 250р, 500р"
val priceRegex = "(\\d+)р".toRegex()
val result = priceRegex.replace(text) { match ->
    val price = match.groupValues[1].toInt()
    "${price * 1.2}р (с НДС)"
}
println(result) // Цены: 120.0р (с НДС), 300.0р (с НДС), 600.0р (с НДС)

Разделение строки (split)

val data = "яблоко,груша;банан|апельсин"
val separators = "[,;|]".toRegex()
val fruits = separators.split(data)
println(fruits) // [яблоко, груша, банан, апельсин]

4. Группы захвата и именованные группы

Группы захвата позволяют извлекать части совпадения. В Kotlin группы нумеруются с 1 (группа 0 — все совпадение).

Нумерованные группы

val dateRegex = "(\\d{2})-(\\d{2})-(\\d{4})".toRegex()
val dateStr = "Дата: 15-03-2025"
val match = dateRegex.find(dateStr)

if (match != null) {
    println("День: ${match.groupValues[1]}")   // 15
    println("Месяц: ${match.groupValues[2]}")  // 03
    println("Год: ${match.groupValues[3]}")    // 2025
    
    // Альтернативный доступ через группы
    println("День: ${match.groups[1]?.value}") // 15
}

Именованные группы

В Kotlin можно использовать именованные группы с синтаксисом (?<имя>...):

val namedRegex = "(?<day>\\d{2})-(?<month>\\d{2})-(?<year>\\d{4})".toRegex()
val namedMatch = namedRegex.find("31-12-2024")

if (namedMatch != null) {                

Блоги

Рекомендаций по книгам