Kata d'exploration des expressions régulières (RegExp).
À propos
ⓘ Ceci est la donnée d'un kata, un exercice de programmation qui se déroule généralement dans le cadre d'un coding dojo. Il est proposé aux membres du dojo de l'EPFL et fait partie d'une collection de différents katas identifiés par le tag epfl-dojo-kata sur GitHub.
Vous êtes plus que bienvenu·e d'essayer de le réaliser dans le langage de programmation de votre choix. Lorsque c'est terminé, ajoutez-vous à la liste de ceux qui l'ont fait dans ce document en proposant une Pull Request. Vous pouvez également partager votre intérêt pour ce dépôt en le «stargazant», c'est à dire en lui ajoutant une ⭐.
Bonne lecture et bon code !
Tout comme git
ou bash
, les expressions régulières sont incontournables dans
le monde de l'informatique. Le but de cet exercice est donc d'apprendre, par la
pratique, cet outil indispensable. Une rapide lecture des pages Wikipedia
Française et
Anglaise est recommandée
pour se faire une idée générale du sujet.
Le document "Learn Regex" permet d'apprendre les mécanismes pas à pas et offrira certainement une bonne source d'information pour réaliser les exercices qui suivent.
Les sites comme regex101 ou regexr.com permettent de tester de manière visuelle les regex et apportent des explications utiles sur les motifs utilisés.
Résumé des méta-caractères tiré de "Learn Regex":
Méta-caractère | Description |
---|---|
. | Un point coïncide avec n'importe quel caractère unique à part le retour à la ligne. |
[ ] | Classe de caractères. Coïncide avec n'importe quel caractère entre crochets. |
[^ ] | Négation de classe de caractère. Coïncide avec n'importe quel caractère qui n'est pas entre les crochets. |
* | Coïncide avec 0 ou plus répétitions du caractère précédent. |
+ | Coïncide avec 1 ou plus répétitions du caractère précédent. |
? | Rend le caractère précédent optionnel. |
{n,m} | Accolades. Coïncide avec au moins "n" mais pas plus que "m" répétition(s) du caractère précédent. |
(xyz) | Groupe de caractères. Coïncide avec les caractères "xyz" dans l'ordre exact. |
| | Alternation (ou). Coïncide soit avec le caractère avant ou après le symbole. |
\ | Échappe le prochain caractère. Cela permet de faire coïncider des caractères réservés tels que [ ] ( ) { } . * + ? ^ $ \ | |
^ | Coïncide avec le début de la chaîne de caractères (string). |
$ | Coïncide avec la fin de la chaîne de caractères (string). |
Ces exercices permettent de mieux comprendre le langage des regex.
💡 si vous avez un langage de prédilection pour appliquer des regex, utilisez-le pour ces exercices. Autrement, regex101, l'un des plus grand service de test de regex dans le monde, est à disposition.
→ But: Le but de cet exercice est de se familiariser avec les outils et les méta-caractères cités ci-dessus.
💡 Note: pour avoir expérimenté cette partie lors d'un dojo, cette partie est à revoir car les derniers points peuvent se réveler très complexes.
Le fichier dict.txt est à disposition pour appliquer les regexp proposées dans cet exercice.
- Trouver la ligne contenant le mot "Malagasy"
- Trouver les mots commençant par "M"
- Trouver les mots commençant par "M", finissant par "o"
- Trouver les mots commençant par "M", finissant par "o" et ayant un "la"
- Trouver les mots avec un double "aa"
- Trouver un moyen (et une variante) de trouver les mots de 7 lettres dans la liste
- Trouver les mots ne commençant pas par "Ma"
- Trouver les termes ayant une majuscule dans le mot à partir du 2ème caractère
- Trouver les mots ne finissant pas par "'s"
- Trouver des syntaxes alternatives à
.*
pour sélectionner des chaînes de caractères - ...
→ But: cet exercice permet de mettre en pratique une RegExp de validation de chaîne de caractère, en l'occurence, une date au format Français non ISO 8601.
Comment valider une date au format jj/mm/aaaa avec une expressions régulière ?
- Exemple de date valide: 01/02/2020
- Exemples de dates invalides:
- 01.02.1337
// séparateurs . plutôt que /
- 01-02-1337
// séparateurs - plutôt que /
- 42/01/1337
// jour impossible
- 31/31/1337
// mois impossible
- 01/1/0001
// mois sur 1 digit
- ab/cd/efgh
// caractères impossible
- 01.02.1337
→ But: manipuler les aspects appris jusqu'ici pour trouver comment identifier des nombres pairs et impaires.
Comment trouver tous les nombres pairs d'une liste ? Et impaires ?
→ But: experimenter un cas concret de validation de pseudo. A noter que le "mais pas que des chiffres" peut être compliqué.
Pour la validation de l'inscription des utilisateurs sur un site internet, vous devez développer le code qui validera les pseudos des utilisateurs. Quelle serait l'expression régulière qui permettrait de valider que :
- le pseudo contient que des lettres minuscules, sans caractères accentués ;
- le pseudo peut contenir des chiffres, mais pas que des chiffres ;
- le pseudo peut contenir des tirets (
-
) et des tirets bas (_
) ; - le pseudo dit avoir de 3 à 15 caractères.
→ But: mieux comprendre les groupes de sélection et éventuellement "dealer" avec
les accents (e.g. avec l'utilisation de [\w]
).
Depuis la source d'une page de cadiwww (e.g. view-source:https://cadiwww.epfl.ch/listes?groupe=epfl-dojo), on veut générer un fichier JSON sous la forme:
{
"111111": "Brandy D. Cantor",
"222222": "Joe King"
}
Quelle serait la regexp qui permettrait d'extraire, en une fois, le numéro sciper et le nom de la personne ?
Le fichier anonymized_list.html peut être utilisé comme source de donnée si pas d'accès au site "cadiwww".
→ But: comprendre qu'on ne peut pas valider une chaine sans comprendre la définition de son format. Aborder la complexité de la RFC 5322.
Note there is no perfect email regex, hence the 99.99%.
(https://emailregex.com)
Beaucoup d'applications doivent gérer des e-mails, les stocker ou les valider. Lors qu'on demande dans quel type de champs on devrait stocker un e- dans une base de donnée à un apprenant, on se rend vite compte que la plupart ont estimé "à la louche" ce que pourrait contenir les adresses e-mail et ne savent pas où rechercher la bonne réponse. Quels sont les caractères autorisés dans la partie locale, la longueur maximale d'une adresse e-mail, les possibilités de nom de domaine.
Cet exercice débute donc avec une série de questions (partie 1):
- Quelle est la longueur maximale de la partie locale d'une adresse e-mail ?
- Quelle est la longueur maximale de la partie nom de domaine d'une adresse e-mail ?
- Par conséquent, quelle est la longueur maximale d'une adresse e-mail ?
- Et minimale ?
- Dans la partie nom de domaine, combien de point peut-on avoir (de ... à ...) ?
- Quels sont les caractères autorisés qui vous surprennent le plus dans la partie locale ?
Pour la suite, utiliser les adresses e-mail du fichier email.md pour tenter de trouver la RegExp compatible avec la norme RFC des e-mails (partie 2).
Pour terminer, lire (et comprendre) comment valider à 100% une adresse e-mail (The 100% correct way).
- https://en.wikipedia.org/wiki/Email_address#Examples
- https://emailregex.com
- https://www.regular-expressions.info/email.html
- https://hackernoon.com/the-100-correct-way-to-validate-email-addresses-7c4818f24643
Pour terminer les exercices, voir "A regular expression to check for prime numbers (noulakaz.net)" : https://news.ycombinator.com/item?id=9039537 / http://montreal.pm.org/tech/neil_kandalgaonkar.shtml
// TODO
Le but de ce kata est de découvrir et pratiquer les expressions régulières. Il y a bien évidemment plusieurs solutions possibles, manières de faires, plus ou moins élégantes ou adéquates pour résoudre un cas. Ci-dessous des propositions de réponse.
Solution pour "Recherche de mots"
- Trouver la ligne contenant "Malagasy"
Malagasy
- Trouver les mots commençant par "M"
^M.*
- Trouver les mots commençant par "M", finissant par "o"
^M.*o$
- Trouver les mots commençant par "M", finissant par "o" et ayant un "la"
^M.*(la).*o$
- Trouver les mots avec un double "aa"
.*(aa).*
^\w*(aa)\w*$
- Trouver un moyen (et une variante) de trouver les mots de 7 lettres dans la liste
/......./
/^\w{7}$/
/^[[:alpha:]]{7}$/
ou/^[[:word:]]{7}$/
/^[A-Za-z]{7}$/
- Trouver les mots ne commençant pas par "Ma"
^(?!Ma).*$
- Trouver les termes ayant une majuscule dans le mot à partir du 2ème caractère
.[A-Z].*
- Trouver les mots ne finissant pas par "'s"
.*(?<!\'s)$
- Trouver des syntaxes alternatives à
.*
pour sélectionner des chaînes de caractères- Voir les classes de caractères
\w
,\W
ou encore[:alpha:]
(Attention de bien noter les différences)
- Voir les classes de caractères
Solution pour "Validation d'une date au format jj-mm-aaaa"
([0-3][0-9])\/([0-1][0-9])\/([0-9]+)
Solution pour "Trouver les nombres pairs et impaires"
Nombre pairs \<\d*[02468]+\> / Impaires \<\d*[13579]+\>
Solution pour "Validation d'un pseudo"
Note: cette solution marche si on ne limite pas le nombre minimum et maximum de caractères dans le pseudo:
[a-z0-9_\-]*[a-z_\-][a-z0-9\-_]*
^(?![0-9])[a-z0-9_\-]{3,15}+
Solution pour "Parser les liens d'une page HTML"
Voir la solution sur https://regex101.com/r/4G0JO8/2
\?sciper=([0-9]{1,})[^0-9]>(.*?)<\/a>
curl https://cadiwww.epfl.ch/listes\?groupe\=epfl-dojo | perl -ne '/sciper=(.+)\">(.+)<\/a>/ && print "${1} ${2}\n"'
Solution pour "Validation d'e-mail" (partie 1)
- Quelle est la longueur maximale de la partie locale d'une adresse e-mail ?
- Quelle est la longueur maximale de la partie nom de domaine d'une adresse e-mail ?
- Par conséquent, quelle est la longueur maximale d'une adresse e-mail ?
- Et minimale ?
- Dans la partie nom de domaine, combien de point peut-on avoir (de ... à ...) ?
- Quels sont les caractères autorisés qui vous surprennent le plus dans la partie locale ?
Solution pour "Validation d'e-mail" (partie 2)
(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
Lire https://www.regular-expressions.info/email.html et https://hackernoon.com/the-100-correct-way-to-validate-e-mail-addresses-7c4818f24643 !
Solution pour "Nombres premiers"
// TODO