Введение в регулярные выражения в Rust
Регулярные выражения (regex) — это мощный инструмент для поиска, извлечения и замены текста по заданному шаблону. В Rust для работы с регулярными выражениями используется крейт regex — одна из самых популярных и производительных библиотек экосистемы. В этой статье мы разберём основы работы с regex в Rust, начиная с установки и заканчивая практическими примерами.
Почему стоит изучить регулярные выражения в Rust? Язык предлагает безопасную и быструю работу с текстом, а крейт regex гарантирует отсутствие утечек памяти и высокую скорость выполнения. Это делает Rust отличным выбором для парсинга логов, валидации форм, обработки конфигурационных файлов и других задач.
Установка и подключение крейта regex
Для начала работы добавьте зависимость regex в ваш файл Cargo.toml:
[dependencies]
regex = "1.10"
После этого импортируйте модуль в коде:
use regex::Regex;
Основная структура, с которой вы будете работать — Regex. Создать экземпляр можно с помощью метода Regex::new(), который возвращает Result, так как шаблон может быть некорректным.
fn main() {
let re = Regex::new(r"^\d{3}-\d{2}-\d{4}$").unwrap();
println!("Regex создан: {}", re.as_str());
}
Обратите внимание: шаблон записывается в сырых строках (r"..."), чтобы избежать экранирования обратных слешей.
Основные операции с регулярными выражениями
1. Проверка совпадения: is_match
Метод is_match возвращает true, если шаблон найден в строке:
use regex::Regex;
fn main() {
let re = Regex::new(r"hello").unwrap();
let text = "hello world";
if re.is_match(text) {
println!("Совпадение найдено!");
} else {
println!("Совпадений нет");
}
}
Вывод: Совпадение найдено!
2. Поиск первого совпадения: find
Метод find возвращает Option<Match> — первое совпадение с информацией о позиции:
use regex::Regex;
fn main() {
let re = Regex::new(r"\d+").unwrap();
let text = "Код: 12345, цена: 678";
if let Some(m) = re.find(text) {
println!("Найдено: '{}' (позиция {}..{})", m.as_str(), m.start(), m.end());
}
}
Вывод: Найдено: '12345' (позиция 5..10)
3. Поиск всех совпадений: find_iter
Для получения всех совпадений используйте итератор find_iter:
use regex::Regex;
fn main() {
let re = Regex::new(r"\d+").unwrap();
let text = "Числа: 42, 100, 7";
for m in re.find_iter(text) {
println!("Число: {}", m.as_str());
}
}
Вывод:
Число: 42
Число: 100
Число: 7
4. Извлечение групп: captures
Группы в шаблоне (обозначаются круглыми скобками) позволяют извлекать части совпадения:
use regex::Regex;
fn main() {
let re = Regex::new(r"(\w+)@(\w+)\.(\w+)").unwrap();
let email = "user@example.com";
if let Some(caps) = re.captures(email) {
println!("Полный email: {}", &caps[0]);
println!("Имя: {}", &caps[1]);
println!("Домен: {}", &caps[2]);
println!("Зона: {}", &caps[3]);
}
}
Вывод:
Полный email: user@example.com
Имя: user
Домен: example
Зона: com
Практические примеры использования
Пример 1: Валидация телефонного номера
Проверим, соответствует ли строка формату российского номера (например, +7-XXX-XXX-XX-XX):
use regex::Regex;
fn validate_phone(phone: &str) -> bool {
let re = Regex::new(r"^\+7-\d{3}-\d{3}-\d{2}-\d{2}$").unwrap();
re.is_match(phone)
}
fn main() {
let phones = vec!["+7-999-123-45-67", "8-999-123-45-67", "+7-999-12-345"];
for phone in phones {
println!("{}: {}", phone, validate_phone(phone));
}
}
Вывод:
+7-999-123-45-67: true
8-999-123-45-67: false
+7-999-12-345: false
Пример 2: Извлечение URL из текста
use regex::Regex;
fn extract_urls(text: &str) -> Vec<String> {
let re = Regex::new(r"https?://[^\s]+").unwrap();
re.find_iter(text)
.map(|m| m.as_str().to_string())
.collect()
}
fn main() {
let text = "Посетите https://rust-lang.org и http://example.com для обучения.";
let urls = extract_urls(text);
println!("Найденные URL:");
for url in urls {
println!(" {}", url);
}
}
Вывод:
Найденные URL:
https://rust-lang.org
http://example.com
Пример 3: Замена текста по шаблону
Метод replace заменяет первое совпадение, а replace_all — все:
use regex::Regex;
fn main() {
let re = Regex::new(r"\bRust\b").unwrap();
let text = "Rust — это язык программирования. Я люблю Rust!";
let result = re.replace_all(text, "Rust🦀");
println!("{}", result);
}
Вывод: Rust🦀 — это язык программирования. Я люблю Rust🦀!
Советы по производительности
Крейт regex в Rust очень быст