Je ne comprends pas vraiment les expressions régulières. Pouvez-vous me les expliquer d'une manière facile à suivre? S'il existe des outils ou des livres en ligne, pourriez-vous également créer un lien vers eux?
La partie la plus importante est les concepts. Une fois que vous avez compris le fonctionnement des blocs de construction, les différences de syntaxe ne représentent guère plus que des dialectes doux. Une couche au-dessus de la syntaxe de votre moteur d'expression régulière est la syntaxe du langage de programmation que vous utilisez. Les langages tels que Perl suppriment la plupart de cette complication, mais vous devrez garder à l'esprit d'autres considérations si vous utilisez des expressions régulières dans un programme C.
Si vous considérez les expressions régulières comme des blocs de construction que vous pouvez mélanger et associer à votre guise, cela vous aide à apprendre à écrire et à déboguer vos propres modèles, mais aussi à comprendre les modèles écrits par d'autres.
Conceptuellement, les expressions régulières les plus simples sont des caractères littéraux. Le motif N
correspond au caractère «N».
Les expressions régulières les unes à côté des autres correspondent aux séquences. Par exemple, le motifNick
correspond à la séquence «N» suivie de «i» suivi de «c» suivi de «k».
Si vous avez déjà utilisé grep
sous Unix - ne serait-ce que pour rechercher des chaînes d'apparence ordinaire - vous avez déjà utilisé des expressions régulières! (Le re
in grep
fait référence aux expressions régulières.)
En ajoutant juste un peu de complexité, vous pouvez faire correspondre «Nick» ou «nick» avec le motif [Nn]ick
. La partie entre crochets est une classe de caractères , ce qui signifie qu'elle correspond exactement à l'un des caractères inclus. Vous pouvez également utiliser des plages dans les classes de caractères.[a-c]
correspond à «a» ou «b» ou «c».
Le motif .
est spécial: plutôt que de correspondre à un point littéral uniquement, il correspond à n'importe quel caractère † . C'est le même concept que la très grande classe de personnages [-.?+%$A-Za-z0-9...]
.
Considérez les classes de caractères comme des menus: choisissez-en un seul.
L'utilisation .
peut vous faire économiser beaucoup de saisie et il existe d'autres raccourcis pour les modèles courants. Disons que vous voulez faire correspondre un chiffre: une façon d'écrire c'est [0-9]
. Les chiffres sont une cible de correspondance fréquente, vous pouvez donc utiliser le raccourci à la place \d
. D'autres sont \s
(espaces) et \w
(caractères de mot: alphanumériques ou trait de soulignement).
Les variantes en majuscules sont leurs compléments, donc \S
correspond à n'importe quel caractère non- blanc, par exemple.
À partir de là, vous pouvez répéter des parties de votre motif avec des quantificateurs . Par exemple, le modèle ab?c
correspond à «abc» ou «ac» car le ?
quantificateur rend le sous-modèle qu'il modifie facultatif. D'autres quantificateurs sont
*
(zéro fois ou plus)+
(une ou plusieurs fois){n}
(exactement n fois){n,}
(au moins n fois){n,m}
(au moins n fois mais pas plus de m fois)En rassemblant certains de ces blocs, le motif [Nn]*ick
correspond à tous
Le premier match démontre une leçon importante: *
réussit toujours!Tout motif peut correspondre à zéro fois.
Quelques autres exemples utiles:
[0-9]+
(et son équivalent \d+
) correspond à tout entier non négatif\d{4}-\d{2}-\d{2}
correspond aux dates au format 01/01/2019Un quantificateur modifie le motif à sa gauche immédiate. Vous pouvez vous attendre 0abc+0
à correspondre à «0abc0», «0abcabc0», et ainsi de suite, mais le modèle immédiatement à gauche du quantificateur plus est c
. Cela signifie 0abc+0
correspond à «0abc0», «0abcc0», «0abccc0», etc.
Pour faire correspondre une ou plusieurs séquences de 'abc' avec des zéros aux extrémités, utilisez 0(abc)+0
. Les parenthèses désignent un sous-modèle qui peut être quantifié comme une unité. Il est également courant que les moteurs d'expressions régulières enregistrent ou «capturent» la partie du texte d'entrée qui correspond à un groupe entre parenthèses. Extraire des bits de cette manière est beaucoup plus flexible et moins sujet aux erreurs que de compter les indices etsubstr
.
Plus tôt, nous avons vu une façon de faire correspondre soit «Nick» ou «nick». Un autre est avec alternance comme dans Nick|nick
. N'oubliez pas que l'alternance comprend tout à sa gauche et tout à sa droite. Utilisez le regroupement entre parenthèses pour limiter la portée de |
, par exemple , (Nick|nick)
.
Pour un autre exemple, vous pouvez écrire de [a-c]
manière équivalente a|b|c
, mais cela risque d'être sous-optimal car de nombreuses implémentations supposent que les alternatives auront des longueurs supérieures à 1.
Bien que certains caractères se correspondent, d'autres ont des significations spéciales. Le modèle \d+
ne correspond pas à la barre oblique inverse suivie d'un D minuscule suivi d'un signe plus: pour obtenir cela, nous utiliserions \\d\+
. Une barre oblique inverse supprime la signification spéciale du caractère suivant.
Les quantificateurs d'expression régulière sont gourmands. Cela signifie qu'ils correspondent à autant de texte que possible tout en permettant à l'ensemble du modèle de correspondre avec succès.
Par exemple, disons que l'entrée est
"Bonjour," dit-elle, "Comment vas-tu?"
Vous pourriez vous attendre ".+"
à correspondre uniquement à «Bonjour», et serez alors surpris de voir qu'il correspond à «Bonjour» tout au long de «vous?».
Pour passer de gourmand à ce que vous pourriez considérer comme prudent, ajoutez un supplément ?
au quantificateur. Vous comprenez maintenant comment fonctionne \((.+?)\)
l'exemple de votre question. Il correspond à la séquence d'une parenthèse gauche littérale, suivie d'un ou plusieurs caractères et terminée par une parenthèse droite.
Si votre entrée est «(123) (456)», la première capture sera «123». Les quantificateurs non gourmands veulent permettre au reste du modèle de commencer à correspondre dès que possible.
(Quant à votre confusion, je ne connais aucun dialecte d'expression régulière où ((.+?))
ferait la même chose. Je soupçonne que quelque chose s'est perdu dans la transmission quelque part en cours de route.)
Utilisez le modèle spécial ^
pour correspondre uniquement au début de votre entrée et $
pour correspondre uniquement à la fin. Faire des «serre-livres» avec vos motifs où vous dites: «Je sais ce qu'il y a à l'avant et à l'arrière, mais donnez-moi tout ce qui se trouve entre» est une technique utile.
Dites que vous souhaitez faire correspondre les commentaires du formulaire
-- This is a comment --
vous écririez ^--\s+(.+)\s+--$
.
Les expressions régulières sont récursives, donc maintenant que vous comprenez ces règles de base, vous pouvez les combiner comme vous le souhaitez.
†: L'énoncé ci-dessus qui .
correspond à n'importe quel caractère est une simplification à des fins pédagogiques qui n'est pas strictement vraie. Le point correspond à n'importe quel caractère sauf le saut de ligne, "\n"
mais dans la pratique, vous vous attendez rarement à un motif tel que .+
le franchissement d'une limite de nouvelle ligne. Les expressions rationnelles Perl ont un /s
commutateur et Java Pattern.DOTALL
, par exemple, pour faire .
correspondre n'importe quel caractère. Pour les langues qui n'ont pas une telle fonctionnalité, vous pouvez utiliser quelque chose comme [\s\S]
pour faire correspondre "n'importe quel espace ou tout autre espace", en d'autres termes n'importe quoi.
a{,m}
n'est pas une chose, du moins en Javascript, Perl et Python.