Введение в регулярные выражения в Swift
Регулярные выражения (regex) — мощный инструмент для поиска, извлечения и замены текста по шаблону. В Swift работа с регулярными выражениями реализована через класс NSRegularExpression из Foundation framework, а также через встроенные методы строк. Это незаменимый инструмент при разработке iOS и macOS приложений для валидации форм, парсинга данных, фильтрации текста и многих других задач.
В этой статье мы разберем основные возможности работы с регулярными выражениями в Swift на практических примерах. Вы узнаете, как создавать шаблоны, выполнять поиск, замену и извлечение данных.
Основы работы с NSRegularExpression
Класс NSRegularExpression — основной способ работы с регулярными выражениями в Swift. Рассмотрим базовые операции.
Создание регулярного выражения
import Foundation
let pattern = "[A-Za-z]+@[A-Za-z]+\\.[A-Za-z]+"
guard let regex = try? NSRegularExpression(pattern: pattern) else {
fatalError("Неверный шаблон")
}
Обратите внимание на двойной слеш \\ — в Swift строки требуют экранирования обратной косой черты.
Поиск первого совпадения
let text = "Свяжитесь с нами по email: support@example.com"
let nsString = text as NSString
let range = NSRange(location: 0, length: nsString.length)
if let match = regex.firstMatch(in: text, range: range) {
let email = nsString.substring(with: match.range)
print("Найден email: \(email)") // support@example.com
}
Поиск всех совпадений
let text = "Контакты: info@site.com, admin@site.com, support@site.com"
let matches = regex.matches(in: text, range: NSRange(location: 0, length: text.count))
for match in matches {
let range = match.range
let email = (text as NSString).substring(with: range)
print(email)
}
// Вывод:
// info@site.com
// admin@site.com
// support@site.com
Использование групп захвата
Группы захвата позволяют извлекать части совпадения. В Swift группы обозначаются круглыми скобками ().
Извлечение данных с помощью групп
let pattern = "(\\d{4})-(\\d{2})-(\\d{2})"
let dateString = "Сегодня: 2024-03-15"
guard let regex = try? NSRegularExpression(pattern: pattern) else { return }
let nsString = dateString as NSString
if let match = regex.firstMatch(in: dateString, range: NSRange(location: 0, length: nsString.length)) {
let fullDate = nsString.substring(with: match.range) // 2024-03-15
let year = nsString.substring(with: match.range(at: 1)) // 2024
let month = nsString.substring(with: match.range(at: 2)) // 03
let day = nsString.substring(with: match.range(at: 3)) // 15
print("Год: \(year), Месяц: \(month), День: \(day)")
}
Именованные группы (работа с Range)
Начиная с Swift 5.7, можно использовать более удобный синтаксис с Range:
let text = "Цена: 1500 рублей"
let pattern = #"(\d+)\sрублей"#
if let range = text.range(of: pattern, options: .regularExpression) {
let match = text[range]
print("Найдено: \(match)") // 1500 рублей
}
Замена текста с помощью регулярных выражений
Одна из самых полезных возможностей — замена частей текста по шаблону.
Простая замена
let text = "Позвоните по номеру +7 (123) 456-78-90"
let pattern = "\\+7\\s\\(\\d{3}\\)\\s\\d{3}-\\d{2}-\\d{2}"
let replacement = "[номер скрыт]"
guard let regex = try? NSRegularExpression(pattern: pattern) else { return }
let modifiedText = regex.stringByReplacingMatches(
in: text,
range: NSRange(location: 0, length: text.count),
withTemplate: replacement
)
print(modifiedText) // Позвоните по номеру [номер скрыт]
Замена с использованием групп
let text = "Иванов Иван, Петров Петр, Сидоров Алексей"
let pattern = "(\\w+)\\s(\\w+)"
let replacement = "$2 $1" // меняем фамилию и имя местами
guard let regex = try? NSRegularExpression(pattern: pattern) else { return }
let result = regex.stringByReplacingMatches(
in: text,
range: NSRange(location: 0, length: text.count),
withTemplate: replacement
)
print(result) // Иван Иванов, Петр Петров, Алексей Сидоров
Практические примеры для iOS/macOS
Валидация email в UITextField
func isValidEmail(_ email: String) -> Bool {
let emailPattern = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format: "SELF MATCHES %@", emailPattern)
return emailPredicate.evaluate(with: email)
}
// Использование
let emailField = UITextField()
emailField.text = "user@example.com"
if isValidEmail(emailField.text ?? "") {
print("Email валидный")
} else {
print("Неверный формат email")
}
Извлечение ссылок из текста
func extractURLs(from text: String) -> [String] {
let pattern = "https?://[\\w./?=&%-]+"
guard let regex = try? NSRegularExpression(pattern: pattern) else { return [] }
let nsString = text as NSString
let results = regex.matches(in: text, range: NSRange(location: 0, length: nsString.length))
return results.map { nsString.substring(with: $0.range) }
}
let text = "Посетите сайт https://example.com или https://pythonlib.ru"
let urls = extractURLs(from: text)
print(urls) // ["https://example.com", "https://pythonlib.ru"]
Фильтрация и очистка текста
func removeHTMLTags(from html: String) -> String {
let pattern = "<[^>]+>"
guard let regex = try? NSRegularExpression(pattern: pattern) else { return html }
return regex.stringByReplacingMatches(
in: html,
range: NSRange(location: 0, length: html.count),
withTemplate: ""
)
}
let htmlString = "<p>Привет, <b>мир</b>!</p>"
let cleanText = removeHTMLTags(from: htmlString)
print