Les ancres en regex : ^, $ et le mode multiligne expliqués
^ et $ ne correspondent pas à des caractères, mais à des positions. Pourquoi un motif sans ancres vérifie moins de choses que vous ne le pensez, ce que change le marqueur m, comment le $ de Python traite un saut de ligne final, et quand utiliser \A et \z à la place.

· 7 min de lecture
/^\d{5}$/
à attraper
- 90210
- 10001
- 02139
- 60614
à épargner
- 9021
- 902100
- ZIP 90210
- 90210-1234
La plupart des éléments d'une regex correspondent à un caractère. Les ancres, elles, correspondent à une position : le début du texte, la fin, l'intervalle entre deux caractères. Elles n'occupent aucune largeur.
Ce sont aussi elles qui manquent le plus souvent dans un motif de validation. Cet article couvre ^ et $, ce que change le marqueur m, et les cas limites qui diffèrent d'un langage à l'autre. Chaque exemple est interactif : modifiez les motifs et regardez les lignes changer.
01Un motif sans ancres vérifie moins que vous ne le pensez
Les moteurs de regex cherchent : ils signalent une correspondance dès que le motif apparaît n'importe où dans le texte. Un motif de « code postal américain à cinq chiffres » sans ancres veut donc en réalité dire « contient cinq chiffres à la suite » :
02^ et $
^ correspond au début du texte et $ à la fin. Placez-les autour du motif, et c'est toute l'entrée qui doit correspondre :
/^\d{5}$/Doit correspondre2/2
- 90210
- 02139
Ne doit pas4/4
- 9021
- 902100
- ZIP 90210
- 90210-1234
Vous pouvez n'en utiliser qu'une. ^# signifie « commence par # », et \.pdf$ signifie « finit par .pdf » :
/\.pdf$/Doit correspondre2/2
- report.pdf
- 2026 taxes.pdf
Ne doit pas2/2
- report.pdf.exe
- pdf-guide.txt
03Les ancres autour d'une alternance
| a la priorité la plus basse de tout le motif, plus basse que celle des ancres. Donc ^cat|dog$ ne veut pas dire « exactement cat ou dog ». Ça veut dire « commence par cat, ou finit par dog » :
Entourez les choix d'un groupe pour que les deux ancres s'appliquent aux deux :
Ce piège se retrouve dans du vrai code, par exemple dans des listes d'autorisation comme ^admin|editor$ qui acceptent sans broncher admin-old ou not-an-editor.
04Le mode multiligne
Par défaut, ^ et $ ne correspondent qu'au tout début et à la toute fin du texte entier, même s'il contient des sauts de ligne. Le marqueur m les fait correspondre au début et à la fin de chaque ligne :
const text = "apple\nbanana\ncherry";
text.match(/^\w+$/g); // null: "apple\nbanana\ncherry" isn't one word
text.match(/^\w+$/gm); // ["apple", "banana", "cherry"]
C'est ce qu'il vous faut quand vous extrayez des éléments d'un fichier ligne par ligne. En Python, c'est re.MULTILINE, ou (?m) au début du motif :
import re
re.findall(r"^#+ .*$", markdown, re.MULTILINE) # every heading line
Le marqueur ne change que ^ et $. Un point ne franchit toujours pas un saut de ligne. Ça, c'est un autre marqueur, s, présenté dans l'article sur les marqueurs de regex.
05Le piège du saut de ligne final
Ici, les langages divergent. En JavaScript, sans m, $ ne correspond qu'à la toute fin. En Python, $ correspond aussi juste avant un saut de ligne situé à la toute fin :
import re
re.match(r"^\d{5}$", "90210\n") # matches in Python
re.fullmatch(r"\d{5}", "90210\n") # None
/^\d{5}$/.test("90210\n"); // false in JavaScript
En Python, ^\d{5}$ accepte donc un code postal suivi d'un saut de ligne. Ça peut compter si la valeur part dans une base de données ou dans un nom de fichier. Deux solutions :
- Utilisez
re.fullmatch(), qui doit consommer toute la chaîne. - Utilisez
\Aet\Z: en Python,\Aest le tout début et\Zla toute fin, sans exception pour le saut de ligne. (Ruby, PCRE et Java écrivent la fin stricte\z.)
JavaScript n'a ni \A ni \z, mais sans le marqueur m, ses ^ et $ se comportent déjà ainsi.
06Les limites de mot sont aussi des ancres
\b est une autre ancre de largeur nulle : la position entre un caractère de mot et un caractère qui n'en est pas un. C'est ainsi qu'on trouve un mot entier dans un texte :
/\bcat\b/Doit correspondre3/3
- the cat sat
- cat
- a cat.
Ne doit pas2/2
- concatenate
- cats
07À vous de jouer
Attrapez les lignes qui sont un hashtag et rien d'autre :
Attrapez les hashtags : un # suivi de lettres, de chiffres ou de tirets bas, et rien d'autre.
Cibles · 0/5 attrapées
- #regexcible
- #100DaysOfCodecible
- #acible
- #snake_casecible
- #2026cible
Innocents · erreurs : 0
- regexinnocent
- ##doubleinnocent
- #two wordsinnocent
- #innocent
- #dash-edinnocent
- a#taginnocent
Tapez une regex — le plateau se met à jour en direct.
08Récapitulatif
- Sans ancres, un motif vérifie seulement que le texte contient une correspondance.
^est le début et$la fin. Utilisez les deux pour valider.- Groupez les alternatives à l'intérieur des ancres :
^(cat|dog)$, pas^cat|dog$. - Le marqueur
mfait fonctionner^et$ligne par ligne. - En Python,
$tolère un saut de ligne final. Utilisezre.fullmatch()ou\Z. \bancre un mot entier.
09Continuez à vous entraîner
- Levez l'ancre et Dompter les lignes sont des packs d'entraînement construits autour des ancres.
- La section du guide sur les ancres en donne la liste complète.