Les expressions régulières sont l’outil indispensable pour détecter, extraire et transformer des patterns dans du texte. En Rust, la crate regex fournit un moteur de regex performant et sûr. Dans cette unité, vous apprendrez à intégrer une dépendance externe, à construire des expressions régulières pour capturer des structures comme des numéros de référence documentaire, et à extraire les groupes capturés.
Ajouter la crate regex au projet
En Rust, les bibliothèques externes s’appellent des crates. On les ajoute dans Cargo.toml ou avec la commande cargo add :
cargo add regex
cargo add once_cell
Cargo modifie automatiquement Cargo.toml :
[dependencies]
regex = "1"
once_cell = "1"
Construire et utiliser un Regex
La construction d’un objet Regex peut échouer si le pattern est invalide, donc elle retourne un Result. Une fois compilé, l’objet peut être réutilisé efficacement :
use regex::Regex;
fn main() {
let re = Regex::new(r"DOC-d{4}-d{3}").unwrap();
let texte = "Voir le document DOC-2024-042 pour les détails.";
println!("Contient une ref : {}", re.is_match(texte));
if let Some(m) = re.find(texte) {
println!("Trouvé : {} (pos {}-{})", m.as_str(), m.start(), m.end());
}
for m in re.find_iter(texte) {
println!("Occurrence : {}", m.as_str());
}
}
Groupes de capture nommés
Les groupes de capture entre parenthèses permettent d’extraire des parties spécifiques. Les groupes nommés ((?P<nom>...)) rendent le code encore plus lisible :
use regex::Regex;
fn main() {
let re = Regex::new(
r"(?P<prefixe>[A-Z]{2,6})-(?P<annee>d{4})-(?P<numero>d{3})"
).unwrap();
let texte = "Références : DOC-2024-042 et FACT-2023-007";
for caps in re.captures_iter(texte) {
println!(
"Préfixe={}, Année={}, N°={}",
&caps["prefixe"], &caps["annee"], &caps["numero"]
);
}
}
Remplacer des patterns
La méthode replace_all permet de substituer toutes les occurrences. Les références aux groupes capturés s’utilisent avec $nom :
use regex::Regex;
fn reformater(texte: &str) -> String {
let re = Regex::new(
r"(?P<prefixe>[A-Z]{2,6})-(?P<annee>d{4})-(?P<numero>d{3})"
).unwrap();
re.replace_all(texte, "[$prefixe] N°$numero/$annee").to_string()
}
fn main() {
let texte = "Voir DOC-2024-042 et FACT-2023-007";
println!("{}", reformater(texte));
// "Voir [DOC] N°042/2024 et [FACT] N°007/2023"
}
Optimiser avec LazyLock
Compiler un Regex à chaque appel de fonction est coûteux. On utilise LazyLock (Rust 1.80+) ou once_cell::sync::Lazy pour ne le compiler qu’une fois :
use once_cell::sync::Lazy;
use regex::Regex;
static RE_REF: Lazy<Regex> = Lazy::new(|| {
Regex::new(r"(?P<prefixe>[A-Z]{2,6})-(?P<annee>d{4})-(?P<numero>d{3})").unwrap()
});
fn detecter(texte: &str) -> bool {
RE_REF.is_match(texte) // RE_REF compilé une seule fois au premier appel
}
- Ajouter une dépendance avec
cargo add nom-crate Regex::new(r"...")— utilisez les raw strings (r"...") pour éviter les doubles backslashes- Les groupes nommés
(?P<nom>...)rendent les captures lisibles - Utilisez
Lazypour compiler le Regex une seule fois au démarrage du programme
📚 Formation : Rust : Développer des utilitaires système

-
Add a note