Si vous ne savez pas ce que expression régulière (également connu sous le nom de "expressions rationnelles" ou "expression rationnelle"), c'est un une langue incroyablement puissante pour exécuter une recherche et/ou un remplacement dans n'importe quel type de texte. Les expressions génériques ont une longue et glorieuse histoire (ses origines remontent aux années 50) et même aujourd'hui, vous l'utilisez tous les jours ... vous ne le savez peut-être pas. Les expressions rationnelles sont intégrées dans la plupart des principaux langages de programmation et systèmes informatiques de nos jours et sont utilisées dans une grande variété d'applications.
Les expressions rationnelles ne sont plus réservées aux programmeurs : elles apparaissent aujourd'hui dans toutes sortes d'endroits. Parmi les endroits où vous avez pu les voir jusqu'à présent, il y a la correspondance des URL dans Google Analytics, la recherche et le remplacement dans votre éditeur de texte préféré (certains éditeurs populaires supportant les regex sont les suivants Sublime, Atome, Cloud9, Bloc-notes++... bien que Word dispose d'une syntaxe d'expressions rationnelles qui est très non standard) et même les noms de fichiers correspondants dans notre génial plugin d'adhésion WordPress, MemberPress.
Même si les expressions rationnelles apparaissent aujourd'hui dans des endroits étonnamment nouveaux, leur nature apparemment cryptique les rendra probablement toujours plus utilisées par les programmeurs et les "utilisateurs chevronnés".
Voici donc le point de cet article où vous devez décider si vous allez continuer à vivre sans connaître la puissance inouïe des regex, ou si vous allez avaler la pilule rouge et manier l'épée d'un utilisateur puissant ! Dans cet article, je vais vous donner les connaissances de base dont vous aurez besoin pour commencer à utiliser cet outil extrêmement utile. C'est parti !
Quelques exemples
À quoi ressemblent les instructions regex ? Si vous en voyez une sans avoir la moindre idée de ce que c'est, vous aurez l'impression d'un véritable charabia.
Voici un exemple d'instruction regexp permettant de faire correspondre un numéro de téléphone :
\(?\d{3}\) ?[- ]\d{3}-\d{4}
En voici un qui correspond à une URL :
https?:\/\/[\w-]+(\.[\w-]{2,})*(:\d{1,5})?
Et qui peut correspondre à une adresse électronique :
[\w\d._%+-]+@[\w\d.-]+\.[\w]{2,4}
Enfin, voici une simple recherche et un remplacement qui trouveront tous les noms de domaine avec le sous-domaine "test" et les remplaceront par un sous-domaine "www" :
Recherche : test.([^\.]+)\c.com
Remplacer : www.$1.com
Vous êtes déjà intimidé ? Ne le soyez pas. J'expliquerai comment les instructions regex sont interprétées, en décomposant ce que nous faisons dans chacune de ces instructions et en expliquant comment créer les vôtres.
Comment lire les expressions rationnelles
Les expressions régulières ressemblent à des instructions de recherche normales, mais sous stéroïdes. Par exemple, si vous voulez trouver le nom "Harry" sur une page web, vous devez cliquer sur contrôle-f et taper "Harry" pour le trouver. Avec les expressions rationnelles, vous pouvez faire plus que simplement rechercher "Harry". Vous pouvez rechercher "Harry" ou "Bob" avec (Harry|Bob)
Vous pouvez également rechercher n'importe quel mot commençant par "Ha" avec Ha\S*
.
Pour votre ordinateur, le texte est représenté par une "chaîne" de caractères. En fait, si vous avez déjà entendu des programmeurs parler de code, vous les avez probablement entendus utiliser le terme "chaîne" pour désigner une variable.
Les expressions régulières se lisent de gauche à droite (tout comme l'anglais et de nombreuses autres langues) et expliquent à l'ordinateur ce qu'il doit faire lorsqu'il parcourt une chaîne de caractères de gauche à droite. Lorsque l'ordinateur examine chaque caractère, il suit ce flux :
Si vous regardez cet organigramme, aussi compliqué qu'il puisse paraître, vous y verrez quelque chose de très familier. C'est à peu près la même chose que ce à quoi on s'attendrait. tous Les Regex ne sont qu'un ajout de fonctionnalités extrêmement puissantes en plus de la recherche normale. Regex ne fait qu'ajouter des fonctionnalités extrêmement puissantes à la recherche normale.
Les bases
Avant de commencer à disséquer nos exemples de regex, examinons les caractères de commande les plus élémentaires de la regex :
Répétiteurs : *, + et {...}
Les caractères astérisque (*) et plus (+) sont des répétiteurs. Un répétiteur n'est utilisé qu'après un autre caractère ou une déclaration fermée et indique à l'ordinateur de faire correspondre le caractère précédent un nombre X de fois. L'astérisque correspondra au caractère précédent de 0 à l'infini ; le plus, de 1 à l'infini ; {2}
correspondra à 2 fois exactement ; {4,6}
correspondra entre 4 et 6 fois exactement ; et {7,}
le fera correspondre entre 7 et une infinité de fois.
Joker : .
Vous êtes probablement habitué à ce que le symbole de l'étoile soit utilisé comme joker, mais c'est un point (.) dans les expressions rationnelles. Le point correspondra simplement à tous caractère.
Facultatif : ?
Comme le répéteur, le caractère facultatif, un point d'interrogation ( ?), n'est utilisé qu'après un autre caractère ou une déclaration fermée. Lorsqu'il est en place, il indique à l'ordinateur que le caractère précédent peut ou non être présent dans les résultats de la recherche.
Début et fin de la chaîne : ^ et $
Lorsque le caret (^) est utilisé au début de la regex, il indique que le premier élément de la chaîne doit être pris en compte. Le signe du dollar ($), lorsqu'il est utilisé à la fin de la regex, correspond à la fin de la chaîne.
Personnages possibles : [...]
Les caractères entre crochets indiquent les caractères qui peuvent être recherchés à cet endroit. Par exemple, si vous souhaitez faire correspondre un "n", un "m", un "l" ou un "_", vous pouvez ajouter ceci à votre expression rationnelle [nml_]
. Si vous voulez simplement faire correspondre n'importe quelle lettre ou n'importe quel chiffre, vous pouvez ajouter ceci [A-Za-z0-9]
.
Si vous voulez faire correspondre n'importe quel caractère sauf les caractères possibles, il suffit de placer un caret (^) après l'accolade d'ouverture. Par exemple, si vous voulez faire correspondre n'importe quel caractère sauf 'x', 'y', 'z' ou '_', vous pouvez le faire avec l'instruction : [^xyz_]
. Comme vous pouvez le constater, cela vous permet de contrôler finement ce que vous faites correspondre, caractère par caractère.
Déclarations ci-jointes : (...)
Il arrive que vous souhaitiez que des sections de votre expression rationnelle se comportent comme un bloc ou qu'elles soient sauvegardées pour plus tard. Pour cela, il suffit d'entourer la déclaration de parenthèses.
Échapper : \
Qu'en est-il si vous souhaitez rechercher les caractères '+', '.', etc. Eh bien, si vous ajoutez une barre oblique inverse devant, cela indiquera à votre ordinateur que vous essayez de trouver un caractère de recherche réel, et de ne pas l'interpréter comme un caractère de commande.
Caractères sténographiques : /s, /S, /d, /D, /w, /W et /b
Ces caractères sont très utiles et vous aideront à faire correspondre certaines séries de caractères. Voici comment ils se décomposent :
/s
correspond à tous les caractères d'espacement tels que l'espace et la tabulation/S
correspond à tous les caractères qui ne sont pas des espaces blancs/d
correspond à n'importe quel caractère numérique/D
correspond à tous les caractères autres que les chiffres/w
correspond à n'importe quel caractère d'un mot (essentiellement alphanumérique)/W
correspond à tout caractère autre qu'un mot/b
correspond à n'importe quelle limite de mot (y compris les espaces, les tirets, les virgules, les points-virgules, etc.)
Bien sûr, il y a beaucoup d'autres choses plus puissantes que vous pouvez faire avec les regex, mais ces bases vous donneront les outils dont vous avez besoin pour 90% vos besoins de recherche avancée.
Ventilation de notre exemple de numéro de téléphone
Maintenant que vous disposez des outils, examinons nos exemples pour voir comment ils fonctionnent, en commençant par notre correspondance pour le numéro de téléphone :
\(?\d{3}\) ?[- ]\d{3}-\d{4}
Nous allons donc procéder à une analyse par déclaration :
\(?
Il s'agit de la première instruction que l'ordinateur recherche. Elle commence par un caractère d'échappement (\) suivi d'une parenthèse ouverte (() suivie d'un caractère facultatif ( ?). Ce caractère indique à l'expression rationnelle qu'elle doit rechercher une parenthèse ouverte pour signaler le début d'un numéro de téléphone, mais que cette parenthèse n'est pas forcément présente dans tous les numéros de téléphone.
\d{3}
La deuxième instruction commence par le caractère abrégé du chiffre (\d), puis comporte un répétiteur ({3}) qui exige qu'il y ait trois chiffres. Elle ne se termine pas par un point d'interrogation car ces trois chiffres ne sont pas facultatifs - ils doivent être présents pour que le résultat de la recherche soit considéré comme un numéro de téléphone.
\)?
Désormais, l'ordinateur vérifiera la présence d'une parenthèse fermante facultative, mais si elle n'est pas présente, la correspondance pourra quand même être établie.
[- ]
Ensuite, nous avons une déclaration de caractères possibles qui recherchera un espace ou un tiret.
\d{3}-\d{4}
Enfin, nous avons quelques déclarations qui attendent 3 chiffres suivis d'un tiret, puis de 4 chiffres.
Vous pouvez voir cela en action et vous amuser avec ici : http://regex101.com/r/nW9iC5/3
Vous remarquerez que cette expression rationnelle ne correspond qu'à deux formats acceptables pour les numéros de téléphone :
(888) 888-8888
888-888-8888
Il ne correspondra pas à une multitude de formats de numéros de téléphone inacceptables tels que
8888888888
88-8888-8888
Mais il volonté correspond également à quelques formats qui pourraient ne pas être appropriés :
(888-888-8888
888) 888-8888
(888)-888-8888
Quelles mesures pensez-vous pouvoir prendre pour vous assurer que cette expression rationnelle ne correspond qu'aux formats appropriés ?
Décomposition de notre URL Regex
Tout d'abord, j'aimerais préciser que la regex suivante n'est en aucun cas une regex de correspondance d'URL complète. Elle ne correspondra qu'à une adresse web sans argument et présente plusieurs autres problèmes, mais elle permettrait de correspondre efficacement à de nombreuses URL.
https?:\/\/[\w-]+(\.[\w-]+)*(:\d{1,5})?
Voici maintenant la répartition :
https?:\N/\N/
Cette première déclaration correspond au protocole de l'URL. Comme le "s" est suivi d'un point d'interrogation, il est facultatif. Il y a également des caractères d'échappement devant les barres obliques, ce qui est généralement le cas dans les expressions rationnelles pour faire correspondre les barres obliques. En réalité, les deux seules façons pour une URL de correspondre à cette déclaration seraient de commencer par http://
ou https://
.
[\w-]+
Ici, nous avons une déclaration de caractères possibles suivie d'un plus. Cela signifie que les caractères suivants doivent être au moins un mot ou un tiret.
(\.[\w-]+)*
Nous avons ici l'instruction qui correspondra à un point suivi de mots ou de tirets. Cette instruction est placée entre parenthèses et suivie d'un plus qui indique à l'ordinateur qu'il peut répéter cette séquence zéro fois ou plus. Ainsi, cette section pourrait correspondre à .memberpress
ou .memberpress.com
ou .memberpress.co.uk
et ainsi de suite.
(:\d{1,5}) ?
Enfin, cette déclaration prévoit l'ajout d'un numéro de port facultatif à la fin de l'URL, qui se compose de deux points suivis de 1 à 5 chiffres, puis de parenthèses et d'un point d'interrogation, ce qui rend la déclaration facultative dans son ensemble.
C'est ici que vous pouvez vous amuser : http://regex101.com/r/vL5uZ2/2
Cette expression rationnelle sera prise en compte :
- https://memberpress.com
- https://memberpress.com
- http://localhost:3000
MAIS il ne correspondra pas aux paramètres qui suivent une URL comme celle-ci :
- http://localhost:3000?test=1&page=5
Que pourriez-vous ajouter à cette expression rationnelle pour qu'elle corresponde à certains paramètres à la fin d'une URL ?
Si vous êtes intéressé par la regex de correspondance d'URL la plus complète (une regex qui correspond aux paramètres, aux caractères unicode, aux grands TLD, etc.) il y en a beaucoup que vous pouvez consulter, mais apparemment le plus complet et le plus précis est celui créé par Diego Perini qui que vous pouvez consulter sur son gist Github.
Décomposition de nos expressions rationnelles pour l'envoi d'e-mails
Une autre utilisation courante des expressions rationnelles consiste à faire correspondre des adresses électroniques. Notre expression rationnelle de correspondance d'adresses électroniques correspondra en fait à un nombre substantiel d'adresses électroniques :
[\w\d\._%+-]+@[\w\d.-]+\.[\w]{2,4}
Voici la répartition :
[\w\d\._%+-]+
Cette instruction correspond à un ou plusieurs caractères verbaux, chiffres, points, caractères de soulignement, symboles de pourcentage, symboles plus ou tirets.
@
Toute adresse électronique a besoin d'un symbole "@" et c'est ce qui correspond bien sûr à cette adresse.
[\w\d.-]+
Après le symbole '@', nous devons commencer par le nom de domaine. Cette déclaration correspondra à un ou plusieurs caractères verbaux, chiffres, points ou tirets.
\.[\w]{2,4}
Nous devons maintenant faire correspondre le domaine de premier niveau, qui est un point suivi de 2 à 4 caractères verbaux.
Vous pouvez également jouer avec cette regex ici : http://regex101.com/r/yQ2wP9/1
Même si cette expression rationnelle n'est pas 100%, elle devrait pouvoir correspondre à la plupart des adresses.
Regex Rechercher et Remplacer
Dans de nombreux cas, il s'agira donc non seulement de faire correspondre des motifs dans votre texte à l'aide de regex, mais aussi d'utiliser la puissance de la recherche et du remplacement à l'aide de regex.
Reprenons l'exemple de la recherche et du remplacement évoqué plus haut :
Recherche : test.([^\.]+)\c.com
Remplacer : www.$1.com
Voici la répartition, en commençant par le modèle de recherche :
test.
Cette première partie correspondra à toute partie de la chaîne commençant par "test".
([^\.]+)
Cette instruction correspondra à un ou plusieurs caractères qui sont tout sauf un point. L'ensemble de l'instruction est placé entre parenthèses pour une raison différente de celle que nous avons vue jusqu'à présent : cette fois, il s'agit de sauvegarder ce qui correspond à cette instruction pour l'utiliser dans le remplacement.
\.com
Enfin, il doit comporter un ".com" à la fin.
Dans le remplacement, nous pouvons utiliser "$1" pour inclure ce que nous avons sauvegardé entre les parenthèses dans le modèle de recherche. Si vous aviez une deuxième déclaration comme celle-ci dans le modèle de recherche, vous pourriez l'utiliser dans le remplacement en utilisant "$2".
Vous pouvez vous amuser avec cette expression de recherche et de remplacement ici : http://regex101.com/r/bW5vX8/1
Ce modèle de recherche présente toutefois de réelles limites. Il ne peut correspondre qu'aux URL commençant par "test." et se terminant par ".com". Comment pensez-vous pouvoir le modifier pour qu'il corresponde aux URL se terminant par ".com", ".net" ou ".org" ?
En savoir plus sur les expressions rationnelles
Cet abécédaire vous a donné un cours accéléré sur les expressions régulières, mais il y a encore beaucoup à apprendre. Vous pouvez obtenir plus d'informations sur les expressions régulières sur Wikipedia (en anglais) ou expressions-regulières.info.
Hey Blair, ce que j'aime dans tes articles, c'est l'originalité des sujets. De nos jours, on lit toujours la même chose... tous ces articles réécrits je ne sais combien de fois. Je lis chacun de vos articles parce que vous utilisez deux choses que peu de spécialistes du marketing utilisent : l'expertise et le professionnalisme. Merci pour ces articles intéressants et s'il vous plaît, continuez dans cette voie. Nous avons tous besoin de gens comme vous 🙂 .
Merci Ivo ...
J'ai un problème avec les formulaires qui enferment l'utilisateur dans un format spécifique pour le numéro de téléphone. Je remarque que sur de nombreux formulaires de contact où les entreprises offrent des services techniques à des utilisateurs internationaux, un numéro de téléphone est requis. Or, en dehors des États-Unis, les numéros de téléphone peuvent avoir des formats différents.
Par exemple :
+45 8765-4321
+43 1-123-456-7890
+46 987-654-321
Dans de nombreux cas, l'utilisateur est obligé de fournir un faux numéro pour remplir le formulaire. Prenons le premier exemple ; par coïncidence, il correspond au format forcé typique de nombreux formulaires en ligne. Cependant, la personne qui lira le formulaire croira que le numéro est celui de l'Oregon et non celui du Danemark. On pourrait penser que les entreprises qui font de la promotion à l'échelle internationale en sont conscientes. Que feriez-vous dans ce cas ?
Laurence, merci pour votre commentaire ... vous soulevez un bon point. Dans cet article, mon expression régulière est assez rigide et liée aux numéros de téléphone américains. Mais ce qui est génial avec les Regex, c'est qu'on peut les rendre aussi souples ou rigides qu'on le souhaite. Par exemple, si je voulais seulement faire correspondre des nombres entiers, des espaces et des tirets éventuellement précédés d'un plus, je pourrais faire ceci :
Cette expression rationnelle correspondrait à chacun des exemples ci-dessus, mais elle est très libérale. Elle correspondrait également à des motifs absurdes tels que :
+– — — —- —
+4-9-1-2-0-1-3-0-2
600-001-001-005-3838-38-28383
Une meilleure approche consisterait peut-être à ne pas autoriser de tirets, d'espaces ou de parenthèses dans le numéro si l'on veut prendre en charge les formats internationaux. Voici un exemple :
Cela correspondrait à tous les chiffres ci-dessus sans tirets :
+4587654321
+4311234567890
+46987654321
Cette solution serait excellente, mais elle est aussi extrêmement libérale ... vous n'auriez aucun moyen de valider le code du pays ou quoi que ce soit d'autre.
Une autre solution possible, si vous savez quels pays vous ciblez, consisterait à traiter tous les formats possibles que vous souhaitez prendre en charge dans votre expression rationnelle de la manière suivante :
Ce modèle correspondrait à chacun de vos trois exemples ci-dessus, mais ne correspondrait à aucun numéro de téléphone américain, etc. Il permet une meilleure validation que les expressions rationnelles ci-dessus parce qu'il est plus rigide... mais il ne validera pas non plus les numéros qui ne font pas partie des codes de pays 45, 43 et 46.
Peut-être qu'en cherchant un peu sur Google, vous pourriez trouver une regex maîtresse pour valider les numéros de téléphone du monde entier. Je n'en ai pas encore trouvé ... alors si vous en trouvez une, faites-le moi savoir. Sinon, vous pourriez écrire votre propre regex complète pour cela (je suis sûr qu'elle serait assez populaire) ... vous n'auriez qu'à utiliser une technique comme celle que j'ai utilisée dans la dernière regex ici ... mais qui englobe tous les formats numériques du monde entier. Un bon début serait de regarder cette page sur wikipedia.
En tout cas, j'espère que cela vous aidera... Je sais que ce n'est pas une solution miracle, mais j'espère que cela pourra au moins vous orienter dans la bonne direction.
Merci pour cet article si instructif et si nécessaire. Je trouve que le codage des expressions rationnelles est souvent considéré comme allant de soi par les personnes qui le connaissent et qui s'attendent généralement à ce que tout le monde le connaisse aussi. Je dispose désormais d'une ressource compréhensible à laquelle je peux me référer.
Je comprends que le contrôle de la conformité des chiffres saisis à une norme prédéfinie est une fonction destinée à minimiser les erreurs. En ce qui concerne les numéros de téléphone internationaux dans un champ de formulaire, je pense qu'il est plus facile de faire confiance à l'utilisateur pour vérifier qu'il a saisi le bon numéro de téléphone que d'essayer de micro-gérer le champ en fonction des nombreuses possibilités. BTW, l'utilisation la plus importante des regex pour moi a été jusqu'à présent dans le fichier .htaccess.
J'apprécie que vous ne répondiez pas seulement aux commentaires sur votre blog, mais que vos réponses soient bien pensées et significatives. C'est un excellent travail.
Merci Laurence.
Très bonne remarque ... mais c'est une partie de la beauté de Regex. Je veux dire que vous n'avez pas besoin de l'utiliser du tout ... mais comme je l'ai dit dans ma première réponse, vous pourriez faire une regex extrêmement légère qui impose simplement d'entrer des chiffres et des tirets ou quelque chose comme ça.
Oui, l'utilisation de Regex avec la directive RedirectMatch est extrêmement utile ... elle facilite grandement le mappage des structures d'url. Il est particulièrement important d'utiliser cela lorsque vous migrez un site où les liens vont tous changer ... Je veux dire que si vous n'utilisez pas une sorte de mappage d'url comme RedirectMatch, votre référencement peut souffrir considérablement lors de la migration de votre site.
Blair,
Merci pour cet article ! J'évite toujours les expressions régulières parce que je n'ai jamais pris le temps de comprendre la syntaxe. Cela permet vraiment de la décomposer et de la rendre plus simple.
Je n'ai plus peur des expressions régulières 🙂 .
Génial Jamie ! Heureux d'avoir pu vous aider !