Qu'est-ce qu'une Regex ?
Les expressions régulières (regex ou regexp) sont des séquences de caractères qui définissent des patterns de recherche. Elles constituent l'un des outils les plus puissants pour le traitement de texte, la reconnaissance de patterns et l'extraction de données.
Pourquoi Utiliser les Expressions Régulières ?
Les regex sont essentielles pour :
- Validation de formulaires (emails, numéros de téléphone, mots de passe)
- Extraction de données (analyse de logs, scraping de pages web)
- Traitement de texte (rechercher et remplacer, formatage)
- Refactoring de code (renommer des variables, mettre à jour la syntaxe)
- Nettoyage d'entrées (sécurité, prévention des attaques par injection)
Comment Lire Cet Aide-Mémoire
Ce guide est organisé en sections progressives :
- Fondamentaux - Syntaxe et patterns de base
- Fonctionnalités Avancées - Lookaround, groupes nommés, Unicode
- Spécifique au Langage - Exemples en Python, JavaScript, PHP, C#, Java, Go, Ruby
- Regex dans VS Code - Transformations rechercher/remplacer avec plus de 20 exemples
- Patterns Courants - Patterns prêts à copier-coller pour emails, URLs, dates, etc.
- Cas d'Usage Pratiques - Applications du monde réel
- Résolution de Problèmes - Erreurs courantes et conseils de performance
Chaque section comprend :
- Des explications claires
- Des exemples visuels
- Des extraits de code que vous pouvez copier
- Des astuces professionnelles et pièges à éviter
Caractères Littéraux
La regex la plus simple est une séquence de caractères littéraux :
abc
Correspond à : "abc" dans "La séquence abc"
Sensibilité à la Casse
Par défaut, les regex sont sensibles à la casse :
Bonjourcorrespond à "Bonjour" mais PAS à "bonjour"- Utilisez le flag
ipour une correspondance insensible à la casse :/bonjour/i
Caractères Spéciaux (Métacaractères)
Ces 12 caractères ont une signification spéciale dans les regex et doivent être échappés avec \ pour correspondre littéralement :
. ^ $ * + ? { } [ ] \ | ( )
Exemples :
\.correspond à un point littéral\€correspond à un symbole euro\(correspond à une parenthèse littérale
| Caractère | Échappement | Exemple | Correspond |
|---|---|---|---|
. (point) |
\. |
3\.14 |
"3.14" |
€ (euro) |
\€ |
\€100 |
"€100" |
* (astérisque) |
\* |
a\*b |
"a*b" |
Classes de Caractères
Classes de Caractères Prédéfinies
| Pattern | Description | Équivalent | Exemple | Correspond |
|---|---|---|---|---|
\d |
N'importe quel chiffre | [0-9] |
\d\d |
"42" |
\D |
N'importe quel non-chiffre | [^0-9] |
\D+ |
"abc" |
\w |
Caractère mot | [a-zA-Z0-9_] |
\w+ |
"bonjour_123" |
\W |
Caractère non-mot | [^a-zA-Z0-9_] |
\W |
"@", "#" |
\s |
Espace blanc | [ \t\n\r\f\v] |
\s+ |
" " (espaces) |
\S |
Non-espace | [^ \t\n\r\f\v] |
\S+ |
"bonjour" |
. |
N'importe quel caractère sauf newline | - | a.c |
"abc", "a1c" |
Astuce Pro : \w N'inclut PAS les lettres Unicode par défaut. Utilisez \p{L} pour le support Unicode (JavaScript/Python).
Classes de Caractères Personnalisées
| Pattern | Description | Exemple | Correspond |
|---|---|---|---|
[abc] |
Correspond à n'importe lequel de a, b, ou c | [aeiou] |
Voyelles : "a", "e", "i", "o", "u" |
[^abc] |
Correspond à tout sauf a, b, ou c | [^0-9] |
Non-chiffres |
[a-z] |
Plage : lettres minuscules | [a-z]+ |
"bonjour" |
[A-Z] |
Plage : lettres majuscules | [A-Z]+ |
"BONJOUR" |
[0-9] |
Plage : chiffres | [0-9]{4} |
"2025" |
[a-zA-Z] |
Combiné : toutes les lettres | [a-zA-Z0-9] |
Alphanumérique |
Exemples :
[aeiou] → Correspond à n'importe quelle voyelle
[^aeiou] → Correspond à n'importe quelle consonne (non-voyelle)
[a-z0-9] → Correspond aux lettres minuscules et chiffres
[a-zA-Z0-9_] → Identique à \w (caractères mot)
Quantificateurs
Les quantificateurs spécifient combien de fois un pattern doit correspondre.
Quantificateurs de Base
| Pattern | Description | Exemple | Correspond |
|---|---|---|---|
* |
0 ou plus | ab*c |
"ac", "abc", "abbc", "abbbc" |
+ |
1 ou plus | ab+c |
"abc", "abbc" (PAS "ac") |
? |
0 ou 1 (optionnel) | colou?r |
"color", "colour" |
{n} |
Exactement n fois | \d{4} |
"2025" (exactement 4 chiffres) |
{n,} |
n ou plus fois | \d{2,} |
"42", "123", "9999" |
{n,m} |
Entre n et m fois | \d{2,4} |
"42", "123", "2025" |
Quantificateurs Gourmands vs. Paresseux
Gourmand (par défaut) : Correspond au maximum possible
<.*> → Correspond : "<div>Bonjour</div>" (chaîne entière)
Paresseux (non-gourmand) : Correspond au minimum possible (ajoutez ? après le quantificateur)
<.*?> → Correspond : "<div>" et "</div>" séparément
| Gourmand | Paresseux | Description |
|---|---|---|
* |
*? |
0 ou plus (paresseux) |
+ |
+? |
1 ou plus (paresseux) |
? |
?? |
0 ou 1 (paresseux) |
{n,m} |
{n,m}? |
Entre n et m (paresseux) |
Exemple :
Texte : "Bonjour" et "Monde"
".*"correspond :"Bonjour" et "Monde"(gourmand)".*?"correspond :"Bonjour"et"Monde"séparément (paresseux)
Ancres et Limites
Les ancres correspondent à des positions, pas des caractères.
| Pattern | Description | Exemple | Correspond |
|---|---|---|---|
^ |
Début de chaîne/ligne | ^Bonjour |
"Bonjour Monde" (au début) |
$ |
Fin de chaîne/ligne | Monde$ |
"Bonjour Monde" (à la fin) |
\b |
Limite de mot | \bchat\b |
"chat" dans "Le chat noir" (PAS "achat") |
\B |
Non-limite de mot | \Bcha |
"achat" (cha PAS à la limite) |
\A |
Début de chaîne (pas ligne) | \ABonjour |
Correspond seulement si "Bonjour" est tout au début |
\z |
Fin de chaîne (pas ligne) | Monde\z |
Correspond seulement si "Monde" est tout à la fin |
\Z |
Fin de chaîne (avant newline final) | Monde\Z |
Correspond "Monde" ou "Monde\n" |
Exemples :
^chat$ → Correspond : "chat" (la ligne entière est "chat")
\bchat\b → Correspond : "chat" dans "le chat noir" (mot entier)
\Bcha → Correspond : "cha" dans "achat" (PAS à la limite)
Mode Multiligne (flag m) :
- Sans
m:^et$correspondent au début/fin de la chaîne entière - Avec
m:^et$correspondent au début/fin de chaque ligne
Groupes et Alternance
Groupes de Capture
Les groupes de capture (...) mémorisent le texte correspondant :
(\d+)-(\d+) → Correspond : "123-456"
Groupe 1 : "123"
Groupe 2 : "456"
Références arrière (réutilise les groupes capturés) :
(\w)\1 → Correspond : "aa", "bb", "cc" (caractère répété)
(\w+) \1 → Correspond : "bonjour bonjour" (mot répété)
Groupes Non-Capturants
Utilisez (?:...) quand vous devez grouper mais n'avez pas besoin de capturer :
(?:https?://) → Groupe "http://" ou "https://" sans capturer
Pourquoi utiliser non-capturant ?
- Meilleures performances (pas de surcharge mémoire)
- Références arrière plus propres (les groupes numérotés ne comptent que les groupes de capture)
Alternance (OU)
Utilisez | pour "correspond à ceci OU cela" :
chat|chien → Correspond : "chat" ou "chien"
gr(i|a)s → Correspond : "gris" ou "gras"
Exemples :
(M|Mme|Dr)\.? → Correspond : "M.", "Mme", "Dr."
https?:// → Correspond : "http://" ou "https://"
Assertions Lookaround
Les lookaround sont des assertions de largeur nulle qui correspondent à une position (comme les ancres) mais avec des conditions.
Lookahead Positif (?=...)
Correspond si le pattern devant correspond (mais ne le consomme pas) :
\d(?=px) → Correspond : "10" dans "10px" (PAS la partie "px")
Cas d'usage : Validation de mot de passe
^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$
Décomposition :
(?=.*[A-Z])- Doit contenir une majuscule(?=.*[a-z])- Doit contenir une minuscule(?=.*\d)- Doit contenir un chiffre(?=.*[@$!%*?&])- Doit contenir un caractère spécial.{8,}- Au moins 8 caractères
Lookahead Négatif (?!...)
Correspond si le pattern devant NE correspond PAS :
\d(?!px) → Correspond : "10" dans "10em" (PAS "10px")
Cas d'usage : Exclure certains mots
\b(?!test)\w+ → Correspond aux mots qui NE commencent PAS par "test"
Lookbehind Positif (?<=...)
Correspond si le pattern derrière correspond :
(?<=€)\d+ → Correspond : "100" dans "€100" (PAS la partie "€")
Cas d'usage : Extraire des prix
(?<=Prix : €)\d+,\d{2} → Correspond : "29,99" dans "Prix : €29,99"
Lookbehind Négatif (?<!...)
Correspond si le pattern derrière NE correspond PAS :
(?<!€)\d+ → Correspond : "100" mais PAS dans "€100"
Tableau Récapitulatif :
| Type | Syntaxe | Description | Exemple |
|---|---|---|---|
| Lookahead Positif | (?=...) |
Correspond si suivi de... | q(?=u) correspond "q" dans "queen" |
| Lookahead Négatif | (?!...) |
Correspond si PAS suivi de... | q(?!u) correspond "q" dans "iraq" |
| Lookbehind Positif | (?<=...) |
Correspond si précédé de... | (?<=€)\d+ correspond "10" dans "€10" |
| Lookbehind Négatif | (?<!...) |
Correspond si PAS précédé de... | (?<!€)\d+ correspond "10" dans "10" |
Groupes de Capture Nommés
Les groupes nommés (?<nom>...) rendent les regex plus lisibles :
JavaScript :
const dateRegex = /(?<annee>\d{4})-(?<mois>\d{2})-(?<jour>\d{2})/;
const match = '2025-01-17'.match(dateRegex);
console.log(match.groups.annee); // "2025"
console.log(match.groups.mois); // "01"
console.log(match.groups.jour); // "17"
Python :
import re
pattern = r'(?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})'
match = re.search(pattern, '2025-01-17')
print(match.group('annee')) # "2025"
print(match.group('mois')) # "01"
print(match.group('jour')) # "17"
C# :
var pattern = @"(?<annee>\d{4})-(?<mois>\d{2})-(?<jour>\d{2})";
var match = Regex.Match("2025-01-17", pattern);
Console.WriteLine(match.Groups["annee"].Value); // "2025"
Groupes Atomiques et Quantificateurs Possessifs
Groupes Atomiques (?>...)
Une fois correspondu, le groupe ne fait pas de retour arrière. Empêche le retour arrière catastrophique :
(?>\d+)bar → Correspond : "123bar" (rapide)
Sans groupe atomique :
\d+bar → Essaie : "123bar", "12bar", "1bar" (lent en cas d'échec)
Quantificateurs Possessifs
| Gourmand | Possessif | Description |
|---|---|---|
* |
*+ |
0 ou plus (pas de retour arrière) |
+ |
++ |
1 ou plus (pas de retour arrière) |
? |
?+ |
0 ou 1 (pas de retour arrière) |
Cas d'usage : Empêcher le retour arrière catastrophique sur les patterns complexes.
Support Unicode
Les moteurs regex modernes supportent les catégories et scripts Unicode.
Catégories Unicode \p{...}
JavaScript (ES2018+) :
const letters = /\p{L}+/u; // N'importe quelle lettre (n'importe quelle langue)
const numbers = /\p{N}+/u; // N'importe quel nombre
const currency = /\p{Sc}/u; // Symboles de devise
Python :
import regex # Note : nécessite le module 'regex', pas 're'
letters = regex.compile(r'\p{L}+')
Catégories Unicode Courantes :
| Catégorie | Description | Exemple |
|---|---|---|
\p{L} |
Lettre | "a", "字", "א" |
\p{N} |
Nombre | "1", "①", "一" |
\p{S} |
Symbole | "$", "©", "♥" |
\p{Sc} |
Symbole devise | "$", "€", "¥" |
\p{P} |
Ponctuation | ".", "!", "?" |
\p{Z} |
Séparateur | Espace, tabulation |
Scripts Unicode :
/\p{Script=Greek}/u → Correspond aux lettres grecques : "α", "β", "γ"
/\p{Script=Cyrillic}/u → Correspond au cyrillique : "а", "б", "в"
/\p{Script=Han}/u → Correspond aux caractères chinois
Négation :
/\P{L}+/u → Correspond à tout ce qui N'est PAS une lettre
Modificateurs et Flags
Les flags changent la façon dont les patterns regex sont interprétés.
| Flag | Nom | Description | Exemple |
|---|---|---|---|
i |
Insensible casse | Ignore la casse | /bonjour/i correspond "Bonjour" |
g |
Global | Trouve toutes les correspondances | /chat/g trouve tous les "chat" |
m |
Multiligne | ^ et $ correspondent débuts/fins de ligne |
/^bonjour/m |
s |
Dotall | . correspond aussi aux newlines |
/a.b/s correspond "a\nb" |
u |
Unicode | Active les fonctionnalités Unicode | /\p{L}+/u |
x |
Étendu | Ignore les espaces blancs (free-spacing) | Permet les commentaires |
y |
Sticky | Correspond à une position exacte | JavaScript uniquement |
Exemples :
Insensible casse (i) :
/bonjour/i.test('BONJOUR') // true
Global (g) :
'chat chien chat'.match(/chat/g) // ["chat", "chat"]
Multiligne (m) :
const text = 'Ligne 1\nLigne 2';
/^Ligne 2/m.test(text) // true (sans 'm' : false)
Dotall (s) :
/a.b/s.test('a\nb') // true (sans 's' : false)
Modificateurs Inline
Appliquer les flags à une partie du pattern :
(?i)bonjour → "bonjour" insensible casse
(?-i)MONDE → "MONDE" sensible casse
(?i:bonjour) → Seulement "bonjour" est insensible casse
Patterns Conditionnels
Syntaxe : (?(condition)vrai|faux)
Exemple : Correspondre aux chaînes entre guillemets ou non
("|')?[^"'\r\n]*(?(1)\1)
Décomposition :
("|')?- Capture optionnellement un guillemet d'ouverture[^"'\r\n]*- Correspond au contenu(?(1)\1)- Si groupe 1 correspond (guillemet ouverture), correspond au même guillemet fermeture
Correspond :
"bonjour"✅'monde'✅test✅ (pas de guillemets)"mixte'❌ (guillemets non correspondants)
Commentaires dans les Regex
Commentaires Inline (?# commentaire)
\d{3}(?# indicatif)-\d{3}(?# central)-\d{4}(?# numéro)
Mode Free-Spacing (flag x)
Ignore les espaces blancs et permet les commentaires :
(?x)
\d{3} # indicatif
- # séparateur
\d{3} # central
- # séparateur
\d{4} # numéro
Beaucoup plus lisible pour les patterns complexes !
Cette section démontre comment utiliser les regex dans 7 langages de programmation populaires. Chaque langage a sa propre API regex, mais la syntaxe des patterns reste largement cohérente.
JavaScript / Node.js
Créer des Patterns Regex
// Notation littérale (la plus courante)
const pattern1 = /\d{3}-\d{4}/;
// Constructeur (quand le pattern est dynamique)
const pattern2 = new RegExp('\\d{3}-\\d{4}');
// Note : Les backslashes doivent être échappés dans les chaînes
// Avec flags
const pattern3 = /bonjour/gi; // Global, insensible casse
Méthodes String
// .match() - Trouve les correspondances
const text = 'Contact : 06 12 34 56 78 ou 06 98 76 54 32';
const matches = text.match(/\d{2} \d{2} \d{2} \d{2} \d{2}/g);
console.log(matches); // ["06 12 34 56 78", "06 98 76 54 32"]
// .matchAll() - Obtenir toutes les correspondances avec groupes (ES2020)
const emailPattern = /([\w.-]+)@([\w.-]+\.[a-z]{2,})/gi;
const emails = 'admin@exemple.fr, user@test.org';
for (const match of emails.matchAll(emailPattern)) {
console.log(`Utilisateur : ${match[1]}, Domaine : ${match[2]}`);
}
// Utilisateur : admin, Domaine : exemple.fr
// Utilisateur : user, Domaine : test.org
// .search() - Trouve la position de la première correspondance
const pos = 'Bonjour Monde'.search(/Monde/);
console.log(pos); // 8
// .replace() - Remplace les correspondances
const phone = '+33 6 12 34 56 78';
const cleaned = phone.replace(/[^\d]/g, '');
console.log(cleaned); // "33612345678"
// .replaceAll() - Remplace toutes les correspondances (ES2021)
const text2 = 'chat chien chat';
const result = text2.replaceAll(/chat/g, 'oiseau');
console.log(result); // "oiseau chien oiseau"
// .split() - Divise par pattern
const csv = 'pomme,banane, orange , raisin';
const fruits = csv.split(/\s*,\s*/);
console.log(fruits); // ["pomme", "banane", "orange", "raisin"]
Méthodes RegExp
// .test() - Retourne un booléen
const isEmail = /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i;
console.log(isEmail.test('user@exemple.fr')); // true
// .exec() - Retourne les détails de la correspondance (ou null)
const pattern = /(\d{4})-(\d{2})-(\d{2})/;
const match = pattern.exec('Date : 2025-01-17');
if (match) {
console.log(match[0]); // "2025-01-17" (correspondance complète)
console.log(match[1]); // "2025" (groupe 1)
console.log(match[2]); // "01" (groupe 2)
console.log(match[3]); // "17" (groupe 3)
}
Groupes Nommés (ES2018+)
const pattern = /(?<annee>\d{4})-(?<mois>\d{2})-(?<jour>\d{2})/;
const match = '2025-01-17'.match(pattern);
console.log(match.groups.annee); // "2025"
console.log(match.groups.mois); // "01"
console.log(match.groups.jour); // "17"
// Références arrière nommées
const dupeWord = /\b(?<mot>\w+)\s+\k<mot>\b/i;
console.log(dupeWord.test('bonjour bonjour')); // true
Support Unicode (ES2018+)
// Correspond à n'importe quelle lettre (incluant accentuées, chinoises, arabes, etc.)
const letters = /\p{L}+/u;
console.log(letters.test('café')); // true
console.log(letters.test('你好')); // true
// Correspond aux emojis
const emoji = /\p{Emoji}/u;
console.log(emoji.test('Bonjour 👋')); // true
Python
Le Module re
import re
# Compiler le pattern (recommandé pour réutilisation)
pattern = re.compile(r'\d{2} \d{2} \d{2} \d{2} \d{2}')
# Ou utiliser directement
re.search(r'\d{2} \d{2} \d{2} \d{2} \d{2}', 'Appelez 06 12 34 56 78')
Fonctions Core
import re
# re.search() - Trouve la première correspondance
match = re.search(r'\d{2} \d{2} \d{2} \d{2} \d{2}', 'Contact : 06 12 34 56 78 ou 06 98 76 54 32')
if match:
print(match.group()) # "06 12 34 56 78"
print(match.start()) # 10 (position)
print(match.end()) # 27
# re.match() - Correspond au DÉBUT de la chaîne
match = re.match(r'\d+', '123 rue de Rivoli')
print(match.group() if match else None) # "123"
match = re.match(r'\d+', 'rue de Rivoli 123')
print(match) # None (ne commence pas par un chiffre)
# re.fullmatch() - Correspond à la chaîne ENTIÈRE
result = re.fullmatch(r'\d{2} \d{2} \d{2} \d{2} \d{2}', '06 12 34 56 78')
print(bool(result)) # True
result = re.fullmatch(r'\d{2} \d{2} \d{2} \d{2} \d{2}', 'Appelez 06 12 34 56 78')
print(bool(result)) # False (texte supplémentaire)
# re.findall() - Trouve toutes les correspondances (retourne une liste)
text = 'Prix : €10, €25, €100'
prices = re.findall(r'€(\d+)', text)
print(prices) # ['10', '25', '100']
# re.finditer() - Trouve toutes les correspondances (retourne un itérateur)
for match in re.finditer(r'€(\d+)', text):
print(f'Trouvé €{match.group(1)} à la position {match.start()}')
# Trouvé €10 à la position 6
# Trouvé €25 à la position 11
# Trouvé €100 à la position 16
# re.sub() - Remplace les correspondances
phone = '+33 6 12 34 56 78'
cleaned = re.sub(r'[^\d]', '', phone)
print(cleaned) # "33612345678"
# re.split() - Divise par pattern
csv = 'pomme,banane, orange , raisin'
fruits = re.split(r'\s*,\s*', csv)
print(fruits) # ['pomme', 'banane', 'orange', 'raisin']
Groupes et Groupes Nommés
import re
# Groupes numérotés
pattern = r'(\d{4})-(\d{2})-(\d{2})'
match = re.search(pattern, 'Date : 2025-01-17')
if match:
print(match.group(0)) # "2025-01-17" (correspondance complète)
print(match.group(1)) # "2025"
print(match.group(2)) # "01"
print(match.group(3)) # "17"
print(match.groups()) # ('2025', '01', '17')
# Groupes nommés (?P<nom>...)
pattern = r'(?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})'
match = re.search(pattern, '2025-01-17')
if match:
print(match.group('annee')) # "2025"
print(match.group('mois')) # "01"
print(match.group('jour')) # "17"
print(match.groupdict()) # {'annee': '2025', 'mois': '01', 'jour': '17'}
Flags
import re
# Insensible casse
re.search(r'bonjour', 'BONJOUR', re.IGNORECASE) # ou re.I
# Multiligne (^ et $ correspondent débuts/fins de ligne)
re.search(r'^Ligne 2', 'Ligne 1\nLigne 2', re.MULTILINE) # ou re.M
# Dotall (. correspond newline)
re.search(r'a.b', 'a\nb', re.DOTALL) # ou re.S
# Verbose (mode free-spacing avec commentaires)
pattern = re.compile(r'''
\d{2} # indicatif
\s # espace
\d{2} # paire 1
\s # espace
\d{2} # paire 2
\s # espace
\d{2} # paire 3
\s # espace
\d{2} # paire 4
''', re.VERBOSE) # ou re.X
# Combiner les flags avec |
pattern = re.compile(r'bonjour', re.IGNORECASE | re.MULTILINE)
Remplacement avec Fonctions
import re
# Utiliser une fonction pour des remplacements dynamiques
def double_number(match):
num = int(match.group())
return str(num * 2)
text = "J'ai 5 pommes et 10 oranges"
result = re.sub(r'\d+', double_number, text)
print(result) # "J'ai 10 pommes et 20 oranges"
# Avec des groupes nommés
def format_name(match):
return f"{match.group('nom').upper()}, {match.group('prenom')}"
pattern = r'(?P<prenom>\w+)\s+(?P<nom>\w+)'
text = 'Jean Dupont'
result = re.sub(pattern, format_name, text)
print(result) # "DUPONT, Jean"
PHP
Fonctions PCRE
<?php
// preg_match() - Trouve la première correspondance
$pattern = '/\d{2} \d{2} \d{2} \d{2} \d{2}/';
$text = 'Contact : 06 12 34 56 78 ou 06 98 76 54 32';
if (preg_match($pattern, $text, $matches)) {
echo $matches[0]; // "06 12 34 56 78"
}
// preg_match_all() - Trouve toutes les correspondances
preg_match_all('/\d{2} \d{2} \d{2} \d{2} \d{2}/', $text, $matches);
print_r($matches[0]); // ["06 12 34 56 78", "06 98 76 54 32"]
// preg_replace() - Remplace les correspondances
$phone = '+33 6 12 34 56 78';
$cleaned = preg_replace('/[^\d]/', '', $phone);
echo $cleaned; // "33612345678"
// preg_split() - Divise par pattern
$csv = 'pomme,banane, orange , raisin';
$fruits = preg_split('/\s*,\s*/', $csv);
print_r($fruits); // ["pomme", "banane", "orange", "raisin"]
// preg_grep() - Filtre un tableau par pattern
$words = ['pomme', 'banane', 'abricot', 'orange'];
$aWords = preg_grep('/^a/', $words);
print_r($aWords); // ["abricot"]
?>
Groupes Nommés
<?php
$pattern = '/(?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})/';
$text = '2025-01-17';
if (preg_match($pattern, $text, $matches)) {
echo $matches['annee']; // "2025"
echo $matches['mois']; // "01"
echo $matches['jour']; // "17"
}
?>
Modificateurs (Flags)
<?php
// i - Insensible casse
preg_match('/bonjour/i', 'BONJOUR'); // Correspond
// m - Multiligne
preg_match('/^Ligne 2/m', "Ligne 1\nLigne 2"); // Correspond
// s - Dotall (. correspond newline)
preg_match('/a.b/s', "a\nb"); // Correspond
// x - Free-spacing (ignore espaces blancs)
$pattern = '/
\d{2} # indicatif
\s # espace
\d{2} # paire 1
\s # espace
\d{2} # paire 2
/x';
// u - Support UTF-8
preg_match('/\w+/u', 'café'); // Correspond (inclut é)
// Combiner les modificateurs
preg_match('/bonjour/imu', $text);
?>
Remplacement avec Callback
<?php
$text = "J'ai 5 pommes et 10 oranges";
$result = preg_replace_callback('/\d+/', function($matches) {
return (int)$matches[0] * 2;
}, $text);
echo $result; // "J'ai 10 pommes et 20 oranges"
?>
C# (.NET)
Classe Regex
using System;
using System.Text.RegularExpressions;
// Méthodes statiques (utilisation simple)
string text = "Contact : 06 12 34 56 78 ou 06 98 76 54 32";
Match match = Regex.Match(text, @"\d{2} \d{2} \d{2} \d{2} \d{2}");
if (match.Success)
{
Console.WriteLine(match.Value); // "06 12 34 56 78"
}
// Trouve toutes les correspondances
MatchCollection matches = Regex.Matches(text, @"\d{2} \d{2} \d{2} \d{2} \d{2}");
foreach (Match m in matches)
{
Console.WriteLine(m.Value);
}
// Sortie :
// 06 12 34 56 78
// 06 98 76 54 32
// Remplace
string phone = "+33 6 12 34 56 78";
string cleaned = Regex.Replace(phone, @"[^\d]", "");
Console.WriteLine(cleaned); // "33612345678"
// Divise
string csv = "pomme,banane, orange , raisin";
string[] fruits = Regex.Split(csv, @"\s*,\s*");
// ["pomme", "banane", "orange", "raisin"]
Regex Compilée (Meilleures Performances)
using System.Text.RegularExpressions;
// Compiler pour réutilisation (beaucoup plus rapide pour utilisation répétée)
Regex pattern = new Regex(@"\d{2} \d{2} \d{2} \d{2} \d{2}", RegexOptions.Compiled);
string text = "Contact : 06 12 34 56 78";
Match match = pattern.Match(text);
if (match.Success)
{
Console.WriteLine(match.Value);
}
RegexOptions (Flags)
using System.Text.RegularExpressions;
// Insensible casse
Regex.IsMatch("BONJOUR", "bonjour", RegexOptions.IgnoreCase);
// Multiligne
Regex.Match("Ligne 1\nLigne 2", "^Ligne 2", RegexOptions.Multiline);
// Singleline (. correspond newline)
Regex.Match("a\nb", "a.b", RegexOptions.Singleline);
// Compilée (meilleures performances)
var pattern = new Regex(@"\d+", RegexOptions.Compiled);
// Combiner les options
var opts = RegexOptions.IgnoreCase | RegexOptions.Multiline;
Regex.Match(text, pattern, opts);
Groupes Nommés
using System;
using System.Text.RegularExpressions;
string pattern = @"(?<annee>\d{4})-(?<mois>\d{2})-(?<jour>\d{2})";
Match match = Regex.Match("2025-01-17", pattern);
if (match.Success)
{
Console.WriteLine(match.Groups["annee"].Value); // "2025"
Console.WriteLine(match.Groups["mois"].Value); // "01"
Console.WriteLine(match.Groups["jour"].Value); // "17"
}
Remplacement avec MatchEvaluator
using System;
using System.Text.RegularExpressions;
string text = "J'ai 5 pommes et 10 oranges";
string result = Regex.Replace(text, @"\d+", match =>
{
int num = int.Parse(match.Value);
return (num * 2).ToString();
});
Console.WriteLine(result); // "J'ai 10 pommes et 20 oranges"
Java
Classes Pattern et Matcher
import java.util.regex.Pattern;
import java.util.regex.Matcher;
// Compiler le pattern
Pattern pattern = Pattern.compile("\\d{2} \\d{2} \\d{2} \\d{2} \\d{2}");
String text = "Contact : 06 12 34 56 78 ou 06 98 76 54 32";
// Créer le matcher
Matcher matcher = pattern.matcher(text);
// Trouve la première correspondance
if (matcher.find()) {
System.out.println(matcher.group()); // "06 12 34 56 78"
}
// Trouve toutes les correspondances
matcher.reset(); // Réinitialise au début
while (matcher.find()) {
System.out.println(matcher.group());
}
// Sortie :
// 06 12 34 56 78
// 06 98 76 54 32
Méthodes String
// matches() - Vérifie si la chaîne ENTIÈRE correspond
boolean isPhone = "06 12 34 56 78".matches("\\d{2} \\d{2} \\d{2} \\d{2} \\d{2}");
System.out.println(isPhone); // true
// replaceAll() - Remplace toutes les correspondances
String phone = "+33 6 12 34 56 78";
String cleaned = phone.replaceAll("[^\\d]", "");
System.out.println(cleaned); // "33612345678"
// replaceFirst() - Remplace la première correspondance
String text = "chat chien chat";
String result = text.replaceFirst("chat", "oiseau");
System.out.println(result); // "oiseau chien chat"
// split() - Divise par pattern
String csv = "pomme,banane, orange , raisin";
String[] fruits = csv.split("\\s*,\\s*");
// ["pomme", "banane", "orange", "raisin"]
Flags Pattern
import java.util.regex.Pattern;
// Insensible casse
Pattern pattern = Pattern.compile("bonjour", Pattern.CASE_INSENSITIVE);
// Multiligne
Pattern.compile("^Ligne 2", Pattern.MULTILINE);
// Dotall (. correspond newline)
Pattern.compile("a.b", Pattern.DOTALL);
// Commentaires (free-spacing)
Pattern.compile("""
\\d{2} # indicatif
\\s # espace
\\d{2} # paire 1
""", Pattern.COMMENTS);
// Combiner les flags
int flags = Pattern.CASE_INSENSITIVE | Pattern.MULTILINE;
Pattern.compile("pattern", flags);
Groupes Nommés
import java.util.regex.Pattern;
import java.util.regex.Matcher;
Pattern pattern = Pattern.compile("(?<annee>\\d{4})-(?<mois>\\d{2})-(?<jour>\\d{2})");
Matcher matcher = pattern.matcher("2025-01-17");
if (matcher.find()) {
System.out.println(matcher.group("annee")); // "2025"
System.out.println(matcher.group("mois")); // "01"
System.out.println(matcher.group("jour")); // "17"
}
Remplacement Avancé
import java.util.regex.Pattern;
import java.util.regex.Matcher;
String text = "J'ai 5 pommes et 10 oranges";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
StringBuffer result = new StringBuffer();
while (matcher.find()) {
int num = Integer.parseInt(matcher.group());
matcher.appendReplacement(result, String.valueOf(num * 2));
}
matcher.appendTail(result);
System.out.println(result); // "J'ai 10 pommes et 20 oranges"
Go (Golang)
Le Package regexp
package main
import (
"fmt"
"regexp"
)
func main() {
// Compiler le pattern
pattern := regexp.MustCompile(`\d{2} \d{2} \d{2} \d{2} \d{2}`)
text := "Contact : 06 12 34 56 78 ou 06 98 76 54 32"
// Trouve la première correspondance
match := pattern.FindString(text)
fmt.Println(match) // "06 12 34 56 78"
// Trouve toutes les correspondances
matches := pattern.FindAllString(text, -1)
fmt.Println(matches) // [06 12 34 56 78 06 98 76 54 32]
// Vérifie si correspond
isMatch := pattern.MatchString("06 12 34 56 78")
fmt.Println(isMatch) // true
// Remplace tout
phone := "+33 6 12 34 56 78"
cleaned := regexp.MustCompile(`[^\d]`).ReplaceAllString(phone, "")
fmt.Println(cleaned) // "33612345678"
// Divise
csv := "pomme,banane, orange , raisin"
fruits := regexp.MustCompile(`\s*,\s*`).Split(csv, -1)
fmt.Println(fruits) // [pomme banane orange raisin]
}
Submatch (Groupes)
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
text := "Date : 2025-01-17"
// FindStringSubmatch retourne [complet, groupe1, groupe2, ...]
matches := pattern.FindStringSubmatch(text)
if matches != nil {
fmt.Println(matches[0]) // "2025-01-17" (correspondance complète)
fmt.Println(matches[1]) // "2025" (groupe 1)
fmt.Println(matches[2]) // "01" (groupe 2)
fmt.Println(matches[3]) // "17" (groupe 3)
}
// FindAllStringSubmatch pour toutes les correspondances
text2 := "Dates : 2025-01-17 et 2024-12-31"
allMatches := pattern.FindAllStringSubmatch(text2, -1)
for _, match := range allMatches {
fmt.Printf("Année : %s, Mois : %s, Jour : %s\n", match[1], match[2], match[3])
}
// Année : 2025, Mois : 01, Jour : 17
// Année : 2024, Mois : 12, Jour : 31
}
Groupes Nommés
package main
import (
"fmt"
"regexp"
)
func main() {
pattern := regexp.MustCompile(`(?P<annee>\d{4})-(?P<mois>\d{2})-(?P<jour>\d{2})`)
text := "2025-01-17"
match := pattern.FindStringSubmatch(text)
if match != nil {
// Obtenir les indices des groupes nommés
names := pattern.SubexpNames()
result := make(map[string]string)
for i, name := range names {
if i != 0 && name != "" {
result[name] = match[i]
}
}
fmt.Println(result["annee"]) // "2025"
fmt.Println(result["mois"]) // "01"
fmt.Println(result["jour"]) // "17"
}
}
Remplacement avec Fonctions
package main
import (
"fmt"
"regexp"
"strconv"
)
func main() {
text := "J'ai 5 pommes et 10 oranges"
pattern := regexp.MustCompile(`\d+`)
result := pattern.ReplaceAllStringFunc(text, func(s string) string {
num, _ := strconv.Atoi(s)
return strconv.Itoa(num * 2)
})
fmt.Println(result) // "J'ai 10 pommes et 20 oranges"
}
Ruby
Littéraux Regex
# Notation littérale
pattern = /\d{2} \d{2} \d{2} \d{2} \d{2}/
# Avec flags
pattern_ci = /bonjour/i # Insensible casse
pattern_multi = /^ligne/m # Multiligne
# Constructeur (pour patterns dynamiques)
pattern = Regex.new('\d{2} \d{2} \d{2} \d{2} \d{2}')
Méthodes String
text = 'Contact : 06 12 34 56 78 ou 06 98 76 54 32'
# match() - Retourne MatchData ou nil
match = text.match(/\d{2} \d{2} \d{2} \d{2} \d{2}/)
if match
puts match[0] # "06 12 34 56 78"
end
# scan() - Trouve toutes les correspondances
matches = text.scan(/\d{2} \d{2} \d{2} \d{2} \d{2}/)
puts matches # ["06 12 34 56 78", "06 98 76 54 32"]
# =~ opérateur - Retourne l'index de la première correspondance
index = text =~ /\d{2} \d{2} \d{2} \d{2} \d{2}/
puts index # 10
# sub() - Remplace la première correspondance
result = 'chat chien chat'.sub(/chat/, 'oiseau')
puts result # "oiseau chien chat"
# gsub() - Remplace toutes les correspondances
phone = '+33 6 12 34 56 78'
cleaned = phone.gsub(/[^\d]/, '')
puts cleaned # "33612345678"
# split() - Divise par pattern
csv = 'pomme,banane, orange , raisin'
fruits = csv.split(/\s*,\s*/)
puts fruits # ["pomme", "banane", "orange", "raisin"]
Groupes de Capture
pattern = /(\d{4})-(\d{2})-(\d{2})/
match = '2025-01-17'.match(pattern)
if match
puts match[0] # "2025-01-17" (correspondance complète)
puts match[1] # "2025" (groupe 1)
puts match[2] # "01" (groupe 2)
puts match[3] # "17" (groupe 3)
end
Groupes Nommés
pattern = /(?<annee>\d{4})-(?<mois>\d{2})-(?<jour>\d{2})/
match = '2025-01-17'.match(pattern)
if match
puts match[:annee] # "2025"
puts match[:mois] # "01"
puts match[:jour] # "17"
end
Remplacement avec Blocs
text = "J'ai 5 pommes et 10 oranges"
result = text.gsub(/\d+/) { |num| (num.to_i * 2).to_s }
puts result # "J'ai 10 pommes et 20 oranges"
# Avec des groupes nommés
pattern = /(?<prenom>\w+)\s+(?<nom>\w+)/
text = 'Jean Dupont'
result = text.gsub(pattern) do |match|
m = Regexp.last_match
"#{m[:nom].upcase}, #{m[:prenom]}"
end
puts result # "DUPONT, Jean"
Flags
# i - Insensible casse
/bonjour/i.match('BONJOUR') # Correspond
# m - Multiligne (. correspond newline)
/a.b/m.match("a\nb") # Correspond
# x - Free-spacing (ignore espaces blancs)
pattern = /
\d{2} # indicatif
\s # espace
\d{2} # paire 1
\s # espace
\d{2} # paire 2
/x
# o - Compiler une fois (optimisation)
pattern = /\d+/o
La fonction Rechercher et Remplacer de Visual Studio Code (Ctrl/Cmd+H) prend en charge les regex avec de puissantes capacités de transformation. Cette section présente 28 exemples pratiques que les développeurs utilisent quotidiennement.
Accéder à Rechercher et Remplacer
Raccourcis Clavier :
- Rechercher :
Ctrl+F(Windows/Linux) /Cmd+F(Mac) - Remplacer :
Ctrl+H(Windows/Linux) /Cmd+H(Mac) - Activer Regex : Cliquez sur le bouton
.*ou appuyez surAlt+R
Astuces :
- Utilisez
Ctrl+Enter(Cmd+Enter) pour tout remplacer - Prévisualisez les correspondances avant de remplacer (elles sont surlignées en jaune)
- Utilisez
F3/Shift+F3pour naviguer entre les correspondances
Transformations Majuscules/Minuscules
VS Code prend en charge des séquences spéciales de remplacement pour la conversion de casse :
| Séquence | Effet | Exemple |
|---|---|---|
\l |
Minuscule caractère suivant | \l |
\u |
Majuscule caractère suivant | \u |
\L |
Minuscule tous les caractères suivants | \L |
\U |
Majuscule tous les caractères suivants | \U |
\E |
Termine la transformation de casse | \U\E |
Exemple 1 : Capitaliser Première Lettre
Rechercher :
\b(\w)(\w*)
Remplacer :
\u$1$2
Avant :
bonjour monde
Après :
Bonjour Monde
Cette section fournit plus de 25 patterns regex prêts à l'emploi.
Validation Email
^[\w.-]+@[\w.-]+\.[a-z]{2,}$
Numéros de Téléphone (France)
^(\+?33|0)[-.\s]?([1-9])[-.\s]?(\d{2})[-.\s]?(\d{2})[-.\s]?(\d{2})[-.\s]?(\d{2})$
Dates (ISO 8601)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
URL
^https?://(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b
Adresses IPv4
^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$
Couleurs Hex
^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$
Mot de Passe Fort
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$
Nom d'Utilisateur (3-16 caractères)
^[a-zA-Z0-9_-]{3,16}$
UUID v4
^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$
Et plus de 15 autres patterns avec documentation complète !
Applications regex du monde réel dans le développement.
Validation de Formulaire
const validators = {
email: /^[\w.-]+@[\w.-]+\.[a-z]{2,}$/i,
phone: /^(\+?33|0)[1-9](\d{2}){4}$/
};
Extraction de Données
Extraire des emails du texte :
import re
emails = re.findall(r'[\w.-]+@[\w.-]+\.[a-z]{2,}', text)
Analyse de Logs
pattern = r'(?P<ip>[\d.]+).+(?P<status>\d{3})'
Refactoring de Code
Convertir d'anciennes appels API dans VS Code :
Rechercher : apiClient\.get\('([^']+)'\)
Remplacer : fetch('$1').then(r => r.json())
Erreurs Courantes
1. Oublier d'Échapper les Caractères Spéciaux
❌ Incorrect : fichier.txt
✅ Correct : fichier\.txt
2. Gourmand vs Paresseux
❌ Gourmand : <.*> correspond à l'ensemble <div>texte</div>
✅ Paresseux : <.*?> correspond à <div> et </div> séparément
3. Ne Pas Utiliser d'Ancres
❌ /\d{3}/ correspond à "123" dans "abc123def"
✅ /^\d{3}$/ correspond uniquement à exactement "123"
Conseils de Performance
- Utilisez des classes de caractères spécifiques au lieu de
. - Ancrez les patterns quand c'est possible
- Évitez les quantificateurs imbriqués (retour arrière catastrophique)
- Utilisez des groupes atomiques pour les performances
- Compilez les patterns pour la réutilisation
Débogage
- Testez sur regex101.com
- Utilisez le mode verbose avec commentaires
- Divisez les patterns complexes en parties
- Testez les cas limites
Outils en Ligne
Testeurs Regex
- regex101.com - Meilleur testeur avec explications
- regexr.com - Constructeur visuel de regex
- regexpal.com - Test simple et rapide
Visualiseurs
- debuggex.com - Diagrammes railroad
- regexper.com - Outil visuel
Ressources d'Apprentissage
- regexone.com - Leçons interactives
- regexlearn.com - Guide pas à pas
- regular-expressions.info - Documentation
Extensions IDE
- Regex Previewer (VS Code)
- Regex Tester (VS Code)
Classes de Caractères
| Pattern | Correspond |
|---|---|
\d |
Chiffre [0-9] |
\w |
Mot [a-zA-Z0-9_] |
\s |
Espace blanc |
. |
N'importe quel caractère |
Quantificateurs
| Pattern | Signification |
|---|---|
* |
0 ou plus |
+ |
1 ou plus |
? |
0 ou 1 |
{n} |
Exactement n |
Ancres
| Pattern | Signification |
|---|---|
^ |
Début ligne |
$ |
Fin ligne |
\b |
Limite mot |
Flags
| Flag | Signification |
|---|---|
i |
Insensible casse |
g |
Global |
m |
Multiligne |
s |
Dotall |
Questions Générales
Q : Quelle est la différence entre les quantificateurs gourmands et paresseux ?
R : Gourmand correspond au maximum possible. Paresseux (*?, +?) correspond au minimum possible.
Q : Comment correspondre à un point littéral ?
R : Échappez-le avec un backslash : \.
Q : Qu'est-ce que le retour arrière catastrophique ?
R : Quand la regex essaie de nombreuses combinaisons, causant de la lenteur. Évitez les quantificateurs imbriqués comme (a+)+.
Q : Les regex peuvent-elles valider parfaitement un email ?
R : Non. Utilisez regex pour le format de base, puis vérifiez via email.
Q : Comment correspondre sur plusieurs lignes ?
R : Utilisez le flag s, ou utilisez [\s\S]* au lieu de .*.
Spécifique VS Code
Q : Comment remplacer avec majuscules dans VS Code ?
R : Utilisez \u (majuscule suivante), \U (majuscule tout).
Q : Puis-je utiliser regex dans la recherche de fichiers de VS Code ?
R : Oui ! Appuyez sur Ctrl+Shift+F et activez regex (Alt+R).
Extension Chrome Regex Data Extractor
Notre Regex Data Extractor vous aide à extraire des données de pages web en utilisant les patterns de ce guide.
Fonctionnalités Clés
- Bibliothèque de Patterns : Patterns pré-construits
- Test en Temps Réel : Testez les regex sur n'importe quelle page web
- Export Multi-Format : CSV, JSON, Excel, PDF
- Extraction par Lot : Extrayez de plusieurs pages
Exemple : Extraire des Emails
- Installez Regex Data Extractor
- Naviguez sur n'importe quelle page web
- Cliquez sur l'icône de l'extension
- Entrez le pattern :
[\w.-]+@[\w.-]+\.[a-z]{2,} - Cliquez sur "Extraire"
- Exportez en CSV/JSON
Exemple : Extraire des Prix
Pattern : €([0-9]{1,3}(?:\s?[0-9]{3})*,?[0-9]{2})
Capture : €1 234,56, €99,99
Astuces Pro
- Sauvegardez les patterns fréquemment utilisés
- Utilisez des groupes nommés pour des données structurées
- Testez d'abord les patterns
- Exportez pour l'analyse de données