Imaginez que vous cherchez une aiguille dans une botte de foin. Imaginez maintenant que vous avez un aimant qui trouve instantanément toutes les aiguilles d'une certaine forme. C'est ainsi que fonctionnent les expressions régulières, un outil puissant pour rechercher et traiter des modèles de texte, qui permet aux développeurs d'économiser des centaines d'heures de travail de routine.
Que sont les expressions régulières
Les expressions régulières (regex ou regexp) sont un langage formel pour décrire des modèles de texte. Elles vous permettent de rechercher, d'extraire et de remplacer du texte selon des règles complexes à l'aide d'une syntaxe compacte. Au lieu d'écrire des dizaines de lignes de code pour valider une adresse e-mail, vous pouvez utiliser une seule expression régulière.
Les expressions régulières sont apparues dans les années 1950 grâce au mathématicien Stephen Kleene, mais elles sont devenues vraiment populaires avec le développement des systèmes Unix et des éditeurs de texte. Aujourd'hui, elles sont prises en charge dans presque tous les langages de programmation.
Syntaxe de base
Commençons par le plus simple. L'expression régulière la plus élémentaire est une chaîne ordinaire. Par exemple, le modèle cat trouvera toutes les occurrences du mot « cat » dans le texte. Mais la véritable puissance des expressions régulières se révèle à travers des caractères spéciaux.
Les métacaractères sont la base de regex :
. — n'importe quel caractère autre que le saut de ligne. Le modèle c.t trouvera « cat », « cut », « c9t », etc.
^ — début de la ligne. L'expression ^Hello ne trouvera « Hello » qu'au début de la ligne.
$ — fin de la ligne. Le modèle world$ ne trouvera « world » qu'à la fin.
* — zéro ou plusieurs répétitions du caractère précédent. Par exemple, go*gle trouvera « ggle », « gogle », « google », « goooogle ».
+ — une ou plusieurs répétitions. Le modèle go+gle trouvera « gogle », « google », mais pas « ggle ».
? — zéro ou une occurrence. L'expression colou?r trouvera à la fois « color » et « colour ».
[] — classe de caractères. Le modèle [aeiou] trouvera n'importe quelle voyelle et [0-9] trouvera n'importe quel chiffre.
| — logique OU. L'expression cat|dog trouvera soit « cat », soit « dog ».
() — groupement. Les parenthèses vous permettent de créer des sous-expressions et de capturer les parties nécessaires du texte.
Exemples pratiques
Examinons les défis réels auxquels sont confrontés les développeurs.
Validation de l'adresse e-mail :
import re
def validate_email(email):
pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
return bool(re.match(pattern, email))
print(validate_email("user@example.com")) # True
print(validate_email("invalid.email")) # FalseCette expression vérifiée par la structure de base de l'e-mail : caractères avant @, nom de domaine et zone.
Extraction des numéros de téléphone :
text = "Contacts: +7(999)123-45-67, 8-800-555-35-35"
pattern = r'[\+\d][\d\-\(\)]{9,}'
phones = re.findall(pattern, text)
print(phones) # ['+7(999)123-45-67', '8-800-555-35-35']Remplacement des données sensibles :
text = "My card number: 1234-5678-9012-3456"
pattern = r'\d{4}-\d{4}-\d{4}-\d{4}'
masked = re.sub(pattern, '****-****-****-****', text)
print(masked) # Mon numéro de carte : **** - **** - **** - ****Analyse de l'URL :
url = "https://example.com:8080/path/to/page?param=value#section"
pattern = r'(?P<protocol>https?://)?(?P<domain>[^:/]+)(?::(?P<port>\d+))?(?P<path>/[^?#]*)?(?:\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?'
match = re.match(pattern, url)
print(match.group('domain')) # example.com
print(match.group('port')) # 8080Techniques avancées
Lookahead et lookbehind — ce sont des outils puissants pour la recherche contextuelle sans capture de texte.
Positive lookahead (?=...) — vérifie que le modèle spécifique se poursuit :
# Trouver les mots suivis d'un point d'exclamation
pattern = r'\w+(?=!)'
text = "Hi! How are you? Great!"
print(re.findall(pattern, text)) # ['Bonjour', 'Excellent']]Negative lookahead (?!...) — vérifie que le motif suivant n'est PAS :
# Trouver les nombres qui ne sont pas suivis du signe de la ruble
pattern = r'\d+(?!₽)'
text = "100₽, 200, 300₽, 400"
print(re.findall(pattern, text)) # ['200', '400']Quantificateurs avides et paresseux :
Par défaut, les quantificateurs sont gourmands — ils capturent le maximum de texte :
text = "<div>First</div><div>Second</div>"
pattern = r'<div>.*</div>'
print(re.findall(pattern, text))
# ['<div>Premier</div><div>Deuxième</div>'] # J'ai tout capturé !En ajoutant ?, nous rendons le quantificateur paresseux :
pattern = r'<div>.*?</div>'
print(re.findall(pattern, text))
# ['<div>Premier</div>', '<div>Deuxième</div>'] # Deux correspondances distinctesGroupes nommés rendre le code lisible :
log = "2024-11-25 14:30:15 ERROR Database connection failed"
pattern = r'(?P<date>\d{4}-\d{2}-\d{2}) (?P<time>\d{2}:\d{2}:\d{2}) (?P<level>\w+) (?P<message>.*)'
match = re.match(pattern, log)
print(match.group('level')) # ERROR
print(match.group('message')) # Database connection failed
Performance et optimisation
Les expressions régulières peuvent être lentes si elles sont mal utilisées. Voici quelques conseils :
Compiler les modèles pour une utilisation multiple :
# Mauvais — compilé à chaque fois
for text in texts:
if re.match(r'\d{3}-\d{3}', text):
process(text)
# Bien — compilé une fois
pattern = re.compile(r'\d{3}-\d{3}')
for text in texts:
if pattern.match(text):
process(text)Évitez le backtracking catastrophique :
Certains modèles peuvent provoquer une croissance exponentielle du temps d'exécution :
# C'est dangereux !
pattern = r'(a+)+'
text = "aaaaaaaaaaaaaaaaaaaaaaaX" # Peut se bloquerCela est dû à de multiples chemins de correspondance en cas d'échec. La solution consiste à utiliser des groupes atomiques ou des quantificateurs possessifs, lorsqu'ils sont pris en charge.
Utilisez des ancres :
# Plus lentement
pattern = r'\d{4}-\d{2}-\d{2}'
# Plus rapide si la date est au début de la ligne
pattern = r'^\d{4}-\d{2}-\d{2}'Débogage des expressions régulières
Les expressions régulières peuvent être difficiles à comprendre. Utilisez des outils de visualisation et de test :
regex101.com — un excellent outil en ligne avec des explications
debuggex.com — visualisation des modèles sous forme de diagrammes
regexr.com - bac à sable interactif avec des conseils
Pour les expressions complexes, ajoutez des commentaires avec le drapeau re.VERBOSE :
pattern = re.compile(r'''
^ # Start of line
(?P<username> # Group for username
[a-zA-Z0-9_]{3,16} # From 3 to 16 alphanumeric characters
)
@ # Symbol @
(?P<domain> # Group for domain
[a-zA-Z0-9.-]+ # Domain name
\.[a-zA-Z]{2,} # Point and zone
)
$ # End of line
'n de ligne
''', re.VERBOSE)Alternatives aux expressions régulières
Regex n'est pas toujours la meilleure solution. Pour certaines tâches, il est préférable d'utiliser des outils spécialisés :
Pour l'analyse HTML, utilisez BeautifulSoup ou lxml au lieu de regex — HTML n'est pas un langage régulier et regex peut donner des résultats imprévisibles.
Pour l'analyse JSON, utilisez les bibliothèques intégrées. Pour les grammaires complexes, envisagez des générateurs d'analyseurs tels que PLY ou ANTLR.
Pour une recherche simple de sous-chaînes, les méthodes de chaîne sont souvent plus rapides et plus faciles à comprendre que les expressions régulières.
Conclusion
Les expressions régulières sont un outil puissant dans l'arsenal du développeur. Elles permettent de gagner du temps, de rendre le code compact et de résoudre des problèmes qui nécessiteraient autrement des dizaines de lignes de code. Commencez par des modèles simples, entraînez-vous sur des tâches réelles et vous maîtriserez progressivement ce langage de modèles. Gardez à l'esprit les performances, utilisez des outils de débogage et n'ayez pas peur d'expérimenter. Au fil du temps, les expressions régulières deviendront une partie naturelle de votre flux de travail.
Vous voulez approfondir vos connaissances en programmation et apprendre à utiliser des outils tels que les expressions régulières dans la pratique ? L'application Code propose des cours structurés sur Python, JavaScript et le développement Web pour les développeurs débutants. Rejoignez notre canal Telegram, où vous trouverez des ressources utiles, des analyses de sujets complexes et le soutien d'une communauté de personnes partageant les mêmes idées prêtes à vous aider dans votre parcours de programmation.
