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

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

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

Начать курс

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

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

1. Создание и базовое использование Regex в Kotlin

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

  • Конструктор класса Regex — передаете строку с шаблоном.
  • Метод-расширение .toRegex() — вызывается на строке.

Примеры создания:

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

// Способ 2: toRegex()
val regex2 = "\\d{3}-\\d{2}-\\d{4}".toRegex()

// С флагами (регистронезависимый поиск)
val regex3 = Regex("hello", RegexOption.IGNORE_CASE)

// Многострочный режим
val regex4 = Regex("^start", RegexOption.MULTILINE)

Обратите внимание: в Kotlin, как и в Java, для экранирования обратного слеша используется двойной слеш \\. Если вы пишете \d — нужно писать "\\d".

2. Основные функции Regex: проверка, поиск, замена

Класс Regex предоставляет несколько ключевых функций для работы со строками.

2.1. Проверка полного совпадения — matches()

Функция matches() возвращает true, если вся строка целиком соответствует шаблону.

val emailRegex = Regex("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")

val email1 = "user@example.com"
val email2 = "invalid-email"

println(emailRegex.matches(email1)) // true
println(emailRegex.matches(email2)) // false

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

Возвращает первое найденное совпадение в виде объекта MatchResult? (или null, если ничего не найдено).

val text = "Мой телефон: 123-45-6789 и еще 987-65-4321"
val phoneRegex = Regex("\\d{3}-\\d{2}-\\d{4}")

val firstMatch = phoneRegex.find(text)
if (firstMatch != null) {
    println("Найден телефон: ${firstMatch.value}") // Найден телефон: 123-45-6789
    println("Начало: ${firstMatch.range.first}")   // Начало: 13
}

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

Возвращает последовательность Sequence<MatchResult> всех непересекающихся совпадений.

val text = "Цены: 100 руб., 250 руб., 50 руб."
val priceRegex = Regex("\\d+")

val prices = priceRegex.findAll(text)
prices.forEach { match ->
    println("Цена: ${match.value}")
}
// Вывод:
// Цена: 100
// Цена: 250
// Цена: 50

2.4. Замена по шаблону — replace()

Функция replace() заменяет все найденные совпадения на указанную строку или результат лямбда-выражения.

val text = "Мой email: john@mail.com и support@site.org"
val emailRegex = Regex("[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}")

// Простая замена
val masked = emailRegex.replace(text, "[EMAIL HIDDEN]")
println(masked) // Мой email: [EMAIL HIDDEN] и [EMAIL HIDDEN]

// Замена с лямбдой (динамическая)
val replaced = emailRegex.replace(text) { match ->
    val local = match.value.split("@")[0]
    "${local.first()}***@***"
}
println(replaced) // Мой email: j***@*** и s***@***

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

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

val text = "яблоко,груша;банан|апельсин"
val separators = Regex("[,;|]")

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

3. Работа с группами захвата

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

val dateStr = "Сегодня 15.03.2024, вчера было 14.03.2024"
val dateRegex = Regex("(\\d{2})\\.(\\d{2})\\.(\\d{4})")

// Извлекаем первую дату
val firstDate = dateRegex.find(dateStr)
if (firstDate != null) {
    println("Полная дата: ${firstDate.value}")         // 15.03.2024
    println("День: ${firstDate.groupValues[1]}")       // 15
    println("Месяц: ${firstDate.groupValues[2]}")      // 03
    println("Год: ${firstDate.groupValues[3]}")         // 2024
}

Именованные группы (синтаксис (?<name>...)):

val namedRegex = Regex("(?<day>\\d{2})\\.(?<month>\\d{2})\\.(?<year>\\d{4})")
val match = namedRegex.find("Дата: 25.12.2023")

if (match != null) {
    println("День: ${match.groups["day"]?.value}")     // 25
    println("Месяц: ${match.groups["month"]?.value}")  // 12
    println("Год: ${match.groups["year"]?.value}")     // 2023
}

4. Продвинутые возможности и флаги

4.1. Флаги регулярных выражений

Kotlin поддерживает все стандартные флаги через enum RegexOption:

Блоги

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

ФлагОписание