Python >> Tutoriel Python >  >> Python Tag >> RegEx

Correspondance d'expression régulière Python

Pourquoi les expressions régulières ont-elles survécu à sept décennies de bouleversements technologiques ? Parce que les codeurs qui comprennent les expressions régulières ont un énorme avantage lorsqu'ils travaillent avec des données textuelles. Ils peuvent écrire en une seule ligne de code ce qui en prend des dizaines à d'autres !

Cet article concerne le re.match() méthode de Python re bibliothèque. Il existe deux méthodes similaires pour vous aider à utiliser les expressions régulières :

  • Le re.findall() facile à utiliser mais moins puissant La méthode renvoie une liste de correspondances de chaînes. Consultez notre tutoriel de blog.
  • Le re.search() La méthode renvoie un objet match de la première correspondance. Consultez notre tutoriel de blog.

Article connexe : Python Regex Superpower - Le guide ultime

Voulez-vous maîtriser la superpuissance des regex ? Découvrez mon nouveau livre La façon la plus intelligente d'apprendre les expressions régulières en Python avec l'approche innovante en 3 étapes pour un apprentissage actif :(1) étudiez un chapitre de livre, (2) résolvez un puzzle de code et (3) regardez une vidéo de chapitre éducatif.

Alors, comment le re.match() travail de méthode ? Étudions la spécification.

Comment fonctionne re.match() en Python ?

Le re.match(pattern, string) La méthode renvoie un objet match si le pattern correspond au début du string . L'objet match contient des informations utiles telles que les groupes correspondants et les positions correspondantes. Un argument optionnel flags vous permet de personnaliser le moteur de regex, par exemple pour ignorer les majuscules.

Spécification :

re.match(pattern, string, flags=0)

Le re.match() la méthode a jusqu'à trois arguments.

  • pattern  :le modèle d'expression régulière que vous souhaitez faire correspondre.
  • string  :la chaîne dans laquelle vous souhaitez rechercher le motif.
  • flags (argument optionnel) :un modificateur plus avancé qui permet de personnaliser le comportement de la fonction. Vous voulez savoir comment utiliser ces drapeaux ? Consultez cet article détaillé sur le blog Finxter.

Nous les explorerons plus en détail plus tard.

Valeur de retour :

Le re.match() La méthode renvoie un objet match. Vous pouvez demander (et à juste titre) :

Qu'est-ce qu'un objet Match ?

Si une expression régulière correspond à une partie de votre chaîne, de nombreuses informations utiles l'accompagnent :quelle est la position exacte de la correspondance ? Quels groupes de regex ont été mis en correspondance et où ?

L'objet match est un simple wrapper pour ces informations. Quelques méthodes regex du re module en Python, tel que re.match() — crée automatiquement un objet de correspondance lors de la première correspondance de motif.

À ce stade, vous n'avez pas besoin d'explorer l'objet match en détail. Sachez simplement que nous pouvons accéder aux positions de début et de fin de la correspondance dans la chaîne en appelant les méthodes m.start() et m.end() sur l'objet match m :

>>> m = re.match('h...o', 'hello world')
>>> m.start()
0
>>> m.end()
5
>>> 'hello world'[m.start():m.end()]
'hello'

Dans la première ligne, vous créez un objet match m en utilisant le re.match() méthode. Le motif 'h...o' correspond dans la chaîne 'hello world' à la position de début 0. Vous utilisez la position de début et de fin pour accéder à la sous-chaîne qui correspond au modèle (en utilisant la technique Python populaire de découpage). Mais notez que comme le match() la méthode tente toujours de faire correspondre uniquement au début de la chaîne, le m.start() retournera toujours zéro.

Maintenant, vous connaissez le but du match() objet en Python. Voyons quelques exemples de re.match() !

Un exemple guidé pour re.match()

Tout d'abord, vous importez le module re et créez la chaîne de texte à rechercher pour les modèles regex :

>>> import re
>>> text = '''
    Ha! let me see her: out, alas! he's cold:
    Her blood is settled, and her joints are stiff;
    Life and these lips have long been separated:
    Death lies on her like an untimely frost
    Upon the sweetest flower of all the field.
'''

Supposons que vous souhaitiez rechercher dans le texte la chaîne "elle" :

>>> re.match('lips', text)
>>>

Le premier argument est le motif à trouver :la chaîne 'lips' . Le deuxième argument est le texte à analyser. Vous avez stocké la chaîne multiligne dans le texte variable, vous le prenez donc comme deuxième argument. Le troisième argument flags du match() méthode est facultative.

Il n'y a pas de sortie ! Cela signifie que le re.match() La méthode n'a pas renvoyé d'objet de correspondance. Pourquoi? Parce qu'au début de la chaîne, il n'y a pas de correspondance pour le modèle regex 'lips' .

Alors, comment pouvons-nous résoudre ce problème ? Simple, en faisant correspondre tous les caractères qui précèdent la chaîne 'lips' dans le texte :

>>> re.match('(.|\n)*lips', text)
<re.Match object; span=(0, 122), match="\n    Ha! let me see her: out, alas! he's cold:\n>

L'expression régulière (.|\n)*lips correspond à tous les préfixes (un nombre arbitraire de caractères, y compris les nouvelles lignes) suivis de la chaîne 'lips' . Cela se traduit par un nouvel objet match qui correspond à une énorme sous-chaîne de la position 0 à la position 122. Notez que l'objet match n'imprime pas toute la sous-chaîne dans le shell. Si vous accédez à la sous-chaîne correspondante, vous obtiendrez le résultat suivant :

>>> m = re.match('(.|\n)*lips', text)
>>> text[m.start():m.end()]
"\n    Ha! let me see her: out, alas! he's cold:\n    Her blood is settled, and her joints are stiff;\n    Life and these lips"

Fait intéressant, vous pouvez également obtenir la même chose en spécifiant le troisième argument de drapeau comme suit :

>>> m = re.match('.*lips', text, flags=re.DOTALL)
>>> text[m.start():m.end()]
"\n    Ha! let me see her: out, alas! he's cold:\n    Her blood is settled, and her joints are stiff;\n    Life and these lips"

Le re.DOTALL flag garantit que l'opérateur point . correspond à tous les caractères y compris le nouveau caractère de ligne.

Quelle est la différence entre re.match() et re.findall() ?

Il y a deux différences entre le re.match(pattern, string) et re.findall(pattern, string) méthodes :

  • re.match(pattern, string) renvoie un objet match tandis que re.findall(pattern, string) renvoie une liste de chaînes correspondantes.
  • re.match(pattern, string) renvoie uniquement la première correspondance dans la chaîne - et uniquement au début - tandis que re.findall(pattern, string) renvoie toutes les correspondances dans la chaîne.

Les deux peuvent être vus dans l'exemple suivant :

>>> text = 'Python is superior to Python'
>>> re.match('Py...n', text)
<re.Match object; span=(0, 6), match='Python'>
>>> re.findall('Py...n', text)
['Python', 'Python']

La chaîne 'Python is superior to Python' contient deux occurrences de 'Python' . Le match() La méthode ne renvoie qu'un objet match de la première occurrence. Le findall() renvoie une liste de toutes les occurrences.

Quelle est la différence entre re.match() et re.search() ?

Les méthodes re.search(pattern, string) et re.match(pattern, string) les deux renvoient un objet match de la première correspondance. Cependant, re.match() tente de faire correspondre le début de la chaîne alors que re.search() correspond n'importe où dans la chaîne.

Vous pouvez voir cette différence dans le code suivant :

>>> text = 'Slim Shady is my name'
>>> re.search('Shady', text)
<re.Match object; span=(5, 10), match='Shady'>
>>> re.match('Shady', text)
>>>

Le re.search() la méthode récupère la correspondance du 'Shady' sous-chaîne en tant qu'objet de correspondance. Mais si vous utilisez le re.match() méthode, il n'y a ni correspondance ni valeur de retour car la sous-chaîne 'Shady' n'apparaît pas au début de la chaîne 'Slim Shady is my name' .

Comment utiliser l'argument de drapeau facultatif ?

Comme vous l'avez vu dans la spécification, le match( ) est fournie avec un troisième 'flag' facultatif argument :

re.match(pattern, string, flags=0)

À quoi sert le flags dispute ?

Les drapeaux vous permettent de contrôler le moteur d'expressions régulières. Parce que les expressions régulières sont si puissantes, elles sont un moyen utile d'activer et de désactiver certaines fonctionnalités (par exemple, s'il faut ignorer les majuscules lors de la correspondance avec votre regex).

Syntaxe Signification
re.ASCII Si vous n'utilisez pas cet indicateur, les symboles spéciaux Python regex \w , \W , \b , \B , \d , \D , \s et \S correspondra aux caractères Unicode. Si vous utilisez cet indicateur, ces symboles spéciaux ne correspondront qu'aux caractères ASCII, comme leur nom l'indique.
re.A Identique à re.ASCII
re.DEBUG Si vous utilisez cet indicateur, Python affichera des informations utiles sur le shell qui vous aideront à déboguer votre regex.
re.IGNORECASE Si vous utilisez cet indicateur, le moteur regex effectuera une correspondance insensible à la casse. Donc, si vous recherchez la classe de caractères [A-Z] , il correspondra également à [a-z] .
re.I Identique à re.IGNORECASE
re.LOCALE N'utilisez jamais ce drapeau. Il est déprécié - l'idée était d'effectuer une correspondance insensible à la casse en fonction de vos paramètres régionaux actuels. Mais ce n'est pas fiable.
re.L Identique à re.LOCALE
re.MULTILINE Cet indicateur active la fonctionnalité suivante :l'expression régulière de début de chaîne '^' correspond au début de chaque ligne (plutôt qu'au début de la chaîne uniquement). Il en va de même pour la regex de fin de chaîne '$' qui correspond désormais également à la fin de chaque ligne dans une chaîne multiligne.
re.M Identique à re.MULTILINE
re.DOTALL Sans utiliser cet indicateur, la regex point '.' correspond à tous les caractères sauf le caractère de saut de ligne '\n' . Activez ce drapeau pour vraiment faire correspondre tous les caractères, y compris le caractère de nouvelle ligne.
re.S Identique à re.DOTALL
re.VERBOSE Pour améliorer la lisibilité des expressions régulières compliquées, vous pouvez autoriser les commentaires et le formatage (multiligne) de la regex elle-même. Ceci est possible avec ce drapeau :tous les caractères d'espacement et les lignes commençant par le caractère '#' sont ignorés dans la regex.
re.X Identique au re.VERBOSE

Voici comment vous l'utiliseriez dans un exemple pratique :

>>> text = 'Python is great!'
>>> re.search('PYTHON', text, flags=re.IGNORECASE)
<re.Match object; span=(0, 6), match='Python'>

Bien que votre regex 'PYTHON' est tout en majuscules, nous ignorons la capitalisation en utilisant le drapeau re.IGNORECASE .


Prochain article