Skip to content

Guide

Aide-mémoire Regex : les modèles essentiels pour tout développeur

Vingt-cinq modèles que vous utiliserez vraiment, la distinction greedy/lazy qui est la source de la moitié des bugs regex, et où JavaScript regex diffère de PCRE.

By Published

Un regex fonctionnel n’est pas une ligne mémorisée ; c’est une ligne plus les hypothèses sur votre entrée et votre variante. Cet aide-mémoire associe chaque modèle à ce qu’il correspond vraiment, les cas limites qu’il manque, et dans quels moteurs regex il fonctionne. Collez-en n’importe lequel dans notre testeur de regex en direct pour voir les correspondances et les captures interactivement.

Notation utilisée ci-dessous

Les modèles sont montrés sans les délimiteurs /.../ environnants sauf où les drapeaux comptent. Supposez que ^ et $ sont ancrés à une valeur unique (tout le champ), pas multi-ligne. Quand un modèle utilise des fonctionnalités non universelles, la note de variante précise dans quels moteurs il fonctionne. Où il y a une forme permissive et stricte, les deux sont données.

Identifiants et noms

Email — permissif

^[^\s@]+@[^\s@]+\.[^\s@]+$

Trois classes de caractères séparées par @ et ., aucune ne contenant d’espace ou d’un autre@. Accepte presque tous les emails du monde réel et rejette les fautes de frappe les plus évidentes. Ne validera pas contre RFC 5322 — les parties locales entre guillemets et les domaines littéraux IP passent ou sont rejetés selon le coin.

Email — spécification de formulaire HTML5

^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$

Le modèle WHATWG spécifie pour HTML input type=“email”. Plus strict que la forme permissive mais ne prétend toujours pas à une couverture RFC 5322 complète — la spec dit explicitement « volontairement non conforme ». Utilisez cela quand vous voulez correspondre au comportement du navigateur.

URL — HTTPS uniquement

^https://[^\s/$.?#].[^\s]*$

URL HTTPS permissive. Rejette les ordures évidentes mais accepte tout après l’hôte qui n’est pas un espace. Pour une vraie validation, déférez à new URL() dans le langage hôte ; le regex sert à filtrer les entrées, pas à les parser.

Slug (identifiant compatible URL)

^[a-z0-9]+(?:-[a-z0-9]+)*$

Lettres minuscules et chiffres avec des traits d’union simples entre les groupes. Pas de tirets en tête ou en fin, pas de doubles tirets. C’est la forme de slug que tout CMS utilise.

Nom d’utilisateur — alphanumérique et underscore, 3-20 chars

^[A-Za-z0-9_]{3,20}$

UUID (toute version)

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$

UUID v4 (strict)

^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$

Applique le 4en position 13 et les bits de variante en position 17 (l’un de 8, 9, a, b). Utilisez cela quand vous vous souciez de la version, pas seulement de la forme.

Nombres, monnaie, codes

Entier (signé)

^-?\d+$

Nombre décimal (signé, partie fractionnaire optionnelle)

^-?\d+(?:\.\d+)?$

Montant en devise (style américain)

^\$?\d{1,3}(?:,\d{3})*(?:\.\d{2})?$

Signe dollar optionnel, séparateurs de milliers tous les trois chiffres, centimes optionnels à deux décimales. Ne gère pas les négatifs ; pour usage comptable, préfixez ^-? ou encapsulez entre parenthèses.

Couleur hex (3, 4, 6 ou 8 chiffres)

^#(?:[0-9a-fA-F]{3,4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$

Les formes à 4 et 8 chiffres incluent un canal alpha (#RRGGBBAA) supporté par CSS Color Level 4 et tous les navigateurs modernes.

Version sémantique (semver 2.0.0)

^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$

C’est le regex canonique publié sur semver.org. Il capture majeur, mineur, patch, pré-version optionnelle, et métadonnées de build optionnelles. Il rejette correctement les zéros de tête dans les composants numériques.

Dates et heures

Date ISO 8601 (YYYY-MM-DD)

^\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01])$

Restreint le mois à 01-12 et le jour à 01-31. Ne valide pas que le jour existe dans le mois donné (le 30 février passe). Pour une vraie validation de date, parsez avec le langage hôte et vérifiez les erreurs.

Horodatage ISO 8601 avec fuseau horaire

^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$

Accepte Z pour UTC ou un décalage numérique comme +02:00. Permet les secondes fractionnaires optionnelles.

Heure HH:MM en format 24h

^(?:[01]\d|2[0-3]):[0-5]\d$

Adresses réseau

IPv4

^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$

Plage d’octet strictement 0-255. Rejette les zéros de tête comme 192.168.001.001(qui est sans ambiguïté pour les humains mais certains systèmes l’interprètent comme octal, donc le rejet est défendable).

IPv6 — pratique

^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$

Correspond à la forme canonique à huit groupes. Ne correspondra pas à IPv6 avec compression :: ou avec IPv4 embarqué comme ::ffff:192.0.2.1. Le regex complet RFC 4291 fait plus de cent caractères ; pour un usage en production, déférez à l’équivalent inet-pton de votre langage.

Adresse MAC

^(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$

Numéro de port

^(?:6553[0-5]|655[0-2]\d|65[0-4]\d{2}|6[0-4]\d{3}|[1-5]\d{4}|[1-9]\d{0,3}|0)$

0-65535, strictement délimité.

Numéros de téléphone

Téléphone américain — permissif

^(?:\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}$

+1 optionnel, parenthèses optionnelles autour du code régional, séparateurs optionnels de tiret, point ou espace. Accepte les formats américains courants ; rejette les numéros non américains.

Téléphone international (E.164)

^\+[1-9]\d{1,14}$

E.164 est la spécification ITU : +de tête, indicatif pays commençant par non-zéro, longueur totale 2-15 chiffres incluant l’indicatif. Pas d’espaces, pas de parenthèses. C’est le format attendu par chaque passerelle SMS et la plupart des CRM.

Chaînes et structure

Chaîne uniquement composée d’espaces

^\s*$

Supprimer les espaces de début/fin (remplacer par vide)

^\s+|\s+$

Réduire les espaces multiples à un seul (remplacer par un espace)

\s{2,}

Correspondre au contenu entre crochets (lazy)

\[([^\]]*)\]

Capture les caractères qui ne sont pas un crochet fermant — la classe de caractères niée est la manière la plus propre de faire un « tout jusqu’au prochain délimiteur » non-greedy.

Comportement des quantificateurs

Greedy (le défaut)

*, +, ? et {n,m} correspondent à autant que possible par défaut, puis reculent pour trouver une correspondance pour le reste du modèle. Sur <b>bonjour</b><b>au revoir</b>, le modèle <b>.*</b> correspond à toute la chaîne, pas à la première paire de balises.

Lazy (suffixe ?)

Ajoutez un ? pour faire correspondre un quantificateur à aussi peu que possible. <b>.*?</b> correspond à <b>bonjour</b> uniquement, ce qui est presque toujours ce que vous vouliez.

Quantificateurs possessifs et groupes atomiques

Les quantificateurs possessifs (*+, ++) et les groupes atomiques ((?>...)) refusent de reculer une fois correspondus. Ils éliminent le retour arrière catastrophique dans les entrées pathologiques. PCRE, Java et Ruby les supportent ; JavaScript ne le fait pas (utilisez une solution de contournement comme un lookahead avec une rétroréférence).

Lookahead et lookbehind

Les lookarounds affirment une condition sans consommer de caractères. Ils sont à largeur nulle.

  • Lookahead positif (?=...) — « suivi de. » \d+(?=px) correspond aux chiffres suivis de px sans inclurepx dans la correspondance.
  • Lookahead négatif (?!...) — « non suivi de. » foo(?!bar) correspond à foo non suivi debar.
  • Lookbehind positif (?<=...)— « précédé de. »
  • Lookbehind négatif (?<!...)— « non précédé de. »

JavaScript supporte le lookahead dans toutes les versions, le lookbehind uniquement à partir d’ES2018. De nombreux moteurs plus anciens (et la version V8 dans certaines builds Node packagées) limitent les lookbehinds aux modèles à largeur fixe ; PCRE et le module regex de Python permettent une largeur variable.

Différences de variantes à retenir

  • JavaScript : pas de quantificateurs possessifs, pas de groupes atomiques, lookbehind depuis ES2018. Le drapeau g(global) fait que String.match retourne toutes les correspondances mais String.replacese comporte différemment — le coin le plus buggé du regex JS.
  • PCRE (Perl Compatible): le superset de fonctionnalités. Utilisé par PHP, nginx, de nombreux outils en ligne de commande. Modèles récursifs, conditionnels, quantificateurs possessifs, groupes atomiques, captures nommées — tout supporté.
  • Python : le module standard re est proche de PCRE moins quelques fonctionnalités. Le module tiers regexajoute le reste plus les lookbehinds à largeur variable et les groupes atomiques.
  • Go (RE2) : délibérément à temps linéaire. Pas de rétroréférences, pas de lookaround. Plus lent sur les modèles simples, immunisé contre le retour arrière catastrophique. Le crate regexde Rust est de la même famille.
  • .NET: similaire à PCRE, plus quelques fonctionnalités uniques comme les groupes d’équilibrage (qui permettent de faire correspondre des crochets imbriqués — d’une manière que les autres variantes ne peuvent pas).

Un drapeau à noter dans toutes les variantes : Unicode property escapes (\p{Letter}, \p{Number}, \p{Script=Greek}) correspondent par catégorie de point de code au lieu de par octet brut. JavaScript a besoin du drapeau u, PCRE a besoin de (*UCP) ou du modificateur /u, Python les supporte dans le module tiers regex. Sans eux, \w signifie uniquement ASCII [A-Za-z0-9_]et votre modèle « correspondre à n’importe quel nom » rejette silencieusement la moitié du monde.

Les modèles à ne jamais écrire

  • Parser HTML.Utilisez un vrai parseur (DOMParser dans le navigateur, BeautifulSoup en Python, go-html en Go). Le regex peut extraire un seul attribut d’une forme bien connue, rien de plus.
  • Parser JSON. Chaque langage a JSON.parse. Utilisez-le.
  • Parser un langage de programmation. Utilisez un combinateur de parseurs ou une vraie grammaire.
  • Tout ce qui doit correspondre à des délimiteurs imbriqués. Les langages réguliers classiques ne peuvent pas compter. Utilisez un parseur.

La conclusion honnête

Le regex est un outil précis avec un domaine petit et bien compris : les chaînes de forme fixe, le filtrage simple des entrées, la recherche-remplacement dans les éditeurs de texte. Les modèles dans cet aide-mémoire couvrent les 80 % des cas qui surviennent dans le code quotidien. Pour les 20 % qui semblent en forme de regex mais ne l’est pas — structures imbriquées, correspondance en langage naturel, validation sémantique — utilisez plutôt un parseur.

Et quand vous écrivez un regex, collez-le dans notre testeuravec trois entrées représentatives et trois entrées pathologiques avant de le committer. Le modèle qui fonctionne sur votre seul cas de test est le modèle qui fait planter la production chez quelqu’un d’autre.

Frequently asked questions

Pourquoi mon regex d&rsquo;email rejette-t-il des adresses valides ?
Parce que la grammaire RFC 5322 pour les adresses email valides fait plus d&rsquo;une page et inclut des constructions comme les parties locales entre guillemets ("nom d&rsquo;utilisateur"@exemple.com) et les domaines littéraux IP (utilisateur@[192.168.0.1]). La plupart des « regex d&rsquo;email » appliquent un tout petit sous-ensemble courant. Pour une vraie validation, envoyez un email de confirmation — le regex ne peut filtrer que les fautes de frappe évidentes.
La variante de regex est-elle vraiment si différente selon les langages ?
Oui. JavaScript supporte le lookahead mais n&rsquo;a obtenu le lookbehind qu&rsquo;en 2018 (ES2018) et les groupes nommés dans la même version. Python utilise re pour le regex basique et regex pour les fonctionnalités avancées comme les modèles récursifs. PCRE a le plus de fonctionnalités et est le plus proche d&rsquo;un « superset de regex ». .NET a ses propres particularités. Testez toujours dans le runtime réel, pas sur regex101 avec la mauvaise variante sélectionnée.
Quantificateurs greedy vs lazy — lequel voulons-nous ?
Greedy (le défaut) correspond à autant que possible ; lazy (suffixe ?) correspond à aussi peu que possible. Pour .* à l&rsquo;intérieur de balises HTML, vous voulez presque toujours lazy : .*? — sinon <b>bonjour</b><b>au revoir</b> correspond à tout depuis le premier <b> jusqu&rsquo;au dernier </b>. Pour l&rsquo;analyse numérique où la longueur du champ est connue, greedy est généralement correct.
Quand ne pas utiliser de regex ?
Pour parser HTML, JSON, YAML, les langages de programmation, ou tout ce qui a une structure imbriquée. Le regex est un outil pour les langages réguliers ; dès que vous avez besoin de compter ou de récursion (correspondance de crochets imbriqués, correspondance de balises ouvertes/fermées), utilisez un vrai parseur. La réponse Stack Overflow « parser HTML avec regex » est devenue un classique culte parce que le conseil est correct.
Quelle est la manière la plus sûre de valider une URL ?
Passez-la au constructeur URL dans le langage réel — new URL(input) en JavaScript, urllib.parse.urlparse en Python, java.net.URI en Java. Ceux-ci implémentent les RFC pertinents et gèrent les cas limites (domaines internationaux, plages de ports, validation de schéma) qu&rsquo;un regex ne gérera pas. Utilisez le regex uniquement pour filtrer la plausibilité syntaxique avant cet appel.
Pourquoi mon regex est-il si lent sur certaines entrées ?
Retour arrière catastrophique. Les modèles avec des quantificateurs imbriqués ou se chevauchant — comme (a+)+ ou (.*).* — peuvent prendre un temps exponentiel sur certaines entrées. La panne mondiale de Cloudflare en juillet 2019 était exactement cela. Atténuations : évitez les quantificateurs imbriqués, utilisez des groupes atomiques (?>...) ou des quantificateurs possessifs dans les variantes qui les supportent, ou utilisez un moteur à temps linéaire comme regex de Rust ou RE2 de Google.

Related

Published May 31, 2026