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

Comment faire correspondre un mot exact dans Python Regex ? (Réponse :non)

La question révèle qu'il peut y avoir des lacunes dans la compréhension des bases de la bibliothèque d'expressions régulières de Python.

Comment faire correspondre un mot ou une chaîne exacte à l'aide d'une expression régulière en Python ?

Donc, si vous êtes une personne impatiente, voici la réponse courte :

Pour faire correspondre une chaîne exacte 'hello' partiellement en 'hello world' , utilisez la simple regex 'hello' . Cependant, une approche plus simple et plus Pythonic utiliserait le in mot-clé dans l'expression d'appartenance 'hello' in 'hello world' .

Pour une correspondance complète, utilisez les symboles de début et de fin '^hello$' qui ne correspondrait pas à la chaîne 'hello world' mais cela correspondrait à 'hello' .

N'hésitez pas à lire la vidéo du didacticiel au fur et à mesure que vous parcourez l'article.

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.


Jusqu'ici tout va bien. Mais plongeons-nous dans des questions plus spécifiques, car vous n'avez peut-être pas exactement cherché cette réponse simpliste.

En fait, il y a plusieurs façons de comprendre votre question et j'ai essayé de trouver toutes les interprétations et j'y ai répondu une par une dans ce tutoriel :

  • Comment vérifier l'appartenance d'un mot à une chaîne sans bibliothèque ?
  • Comment faire correspondre une chaîne exacte à l'aide de la bibliothèque regex de Python ?
  • Comment faire correspondre un mot dans une chaîne en utilisant les limites de mots \b ?
  • Comment faire correspondre un mot dans une chaîne (insensible à la casse) ?
  • Comment trouver toutes les occurrences d'un mot dans une chaîne ?
  • Comment trouver toutes les lignes contenant un mot exact ?

Plongeons-nous dans chacun d'eux dans l'article restant pour apprendre et améliorer vos super-pouvoirs regex !

Comment vérifier l'appartenance d'un mot à une chaîne (Python intégré) ?

Pour faire correspondre une chaîne exacte 'hello' dans une chaîne telle que 'hello world' , utilisez le in mot-clé dans l'expression d'appartenance 'hello' in 'hello world' .

C'est la réponse simple, vous avez déjà appris.

Au lieu de faire correspondre une chaîne exacte, il suffit souvent d'utiliser le in de Python mot-clé pour vérifier l'appartenance. Comme il s'agit d'une fonctionnalité intégrée très efficace dans Python, elle est beaucoup plus rapide, plus lisible et ne nécessite pas de dépendances externes.

Ainsi, vous devriez vous fier à cette méthode si possible :

>>> 'hello' in 'hello world'
True

Le premier exemple montre la manière la plus simple de procéder :il suffit de demander à Python si une chaîne est "dans" une autre chaîne. C'est ce qu'on appelle l'opérateur d'adhésion et c'est très efficace.

Vous pouvez également vérifier si une chaîne ne le fait pas apparaître dans une autre chaîne.

Voici comment :

>>> 'hi' not in 'hello world'
True

L'opérateur d'appartenance négatif s1 not in s2 renvoie True si chaîne s1 n'apparaît pas dans la chaîne s2 .

Mais il y a un problème avec l'opérateur d'adhésion. La valeur de retour est une valeur booléenne.

Cependant, l'avantage de la bibliothèque d'expressions régulières de Python re est qu'il renvoie un objet match qui contient des informations plus intéressantes telles que l'emplacement exact de la sous-chaîne correspondante.

Explorons ensuite le problème de la correspondance exacte des chaînes à l'aide de la bibliothèque regex :

Comment faire correspondre une chaîne exacte (Regex) ?

Pour faire correspondre une chaîne exacte à l'aide de la bibliothèque regex de Python re , utilisez la chaîne comme expression régulière. Par exemple, vous pouvez appeler le re.search('hello', 'hello world') pour correspondre à la chaîne exacte 'hello' dans la chaîne 'hello world' et renvoie un objet match.

Voici comment faire correspondre une sous-chaîne exacte dans une chaîne donnée :

>>> import re
>>> re.search('hello', 'hello world')
<re.Match object; span=(0, 5), match='hello'>

Après avoir importé la bibliothèque de Python pour le traitement des expressions régulières re , vous utilisez le re.search(pattern, string) méthode pour trouver la première occurrence du pattern dans le string .

💡 Tutoriel associé  :Si vous n'êtes pas sûr du re.search() méthode, consultez mon tutoriel détaillé sur ce blog.

Cela renvoie un objet match qui contient de nombreuses informations utiles telles que les positions de début et de fin de correspondance et la sous-chaîne correspondante.

Comme vous recherchez des correspondances de chaînes exactes, la sous-chaîne correspondante sera toujours la même que le mot recherché.

Mais attendez, il y a un autre problème :vous vouliez une correspondance exacte, n'est-ce pas ?

L'utilisation de l'approche précédente n'aide pas car vous obtenez des correspondances de préfixe du mot recherché :

>>> re.search('good', 'goodbye')
<re.Match object; span=(0, 4), match='good'>

Lors de la recherche du mot exact 'good' dans la chaîne 'goodbye' il correspond en fait au préfixe du mot.

C'est ce que tu voulais? Sinon, lisez la suite :

Comment faire correspondre un mot dans une chaîne (limite de mot \b) ?

Une correspondance exacte d'un mot récupérera également les sous-chaînes correspondantes qui se produisent n'importe où dans la chaîne.

Voici un exemple :

>>> 'no' in 'nobody knows'
True

Et un autre exemple :

>>> re.search('see', 'dfjkyldsssseels')
<re.Match object; span=(10, 13), match='see'>

Et si vous voulez faire correspondre uniquement des mots entiers, et non des sous-chaînes exactes ?

La réponse est simple :

Pour faire correspondre des mots exacts entiers, utilisez le métacaractère de limite de mot '\b' . Ce métacaractère correspond au début et à la fin de chaque mot, mais il ne consomme rien. En d'autres termes, il vérifie simplement si le mot commence ou se termine à cette position (en vérifiant les espaces ou les caractères non verbaux).

Voici comment vous utilisez le caractère de limite de mot pour vous assurer que seuls les mots entiers correspondent :

>>> import re
>>> re.search(r'\bno\b', 'nobody knows')
>>> 
>>> re.search(r'\bno\b', 'nobody knows nothing - no?')
<re.Match object; span=(23, 25), match='no'>

Dans les deux exemples, vous utilisez la même regex '\bno\b' qui recherche le mot exact 'no' mais seulement si le caractère limite du mot '\b' matchs avant et après.

En d'autres termes, le mot 'no' doit apparaître seul comme un mot séparé. Il n'est pas autorisé d'apparaître dans une autre séquence de caractères de mot.

Par conséquent, l'expression régulière ne correspond pas dans la chaîne 'nobody knows' mais il correspond dans la chaîne 'nobody knows nothing - no?' .

Notez que nous utilisons la chaîne brute r'...' pour écrire la regex afin que la séquence d'échappement '\b' fonctionne dans la chaîne.

  • Sans la chaîne brute, Python supposerait qu'il s'agit d'un caractère antislash non échappé '\' , suivi du caractère 'b' .
  • Avec la chaîne brute, toutes les barres obliques inverses ne seront que cela :des barres obliques inverses. Le moteur regex interprète alors les deux caractères comme un métacaractère spécial :la limite de mot '\b' .

Mais que se passe-t-il si vous ne vous souciez pas de savoir si le mot est en majuscule, en minuscule ou en majuscule ? En d'autres termes :

Comment faire correspondre un mot dans une chaîne (insensible à la casse) ?

Vous pouvez rechercher un mot exact dans une chaîne, mais ignorez les majuscules. De cette façon, peu importe que les caractères du mot soient en minuscules ou en majuscules.

Voici comment :

>>> import re
>>> re.search('no', 'NONONON', flags=re.IGNORECASE)
<re.Match object; span=(0, 2), match='NO'>
>>> re.search('no', 'NONONON', flags=re.I)
<re.Match object; span=(0, 2), match='NO'>
>>> re.search('(?i)no', 'NONONON')
<re.Match object; span=(0, 2), match='NO'>

Les trois manières sont équivalentes :elles ignorent toutes la capitalisation des lettres du mot.

💡 Tutoriel associé : Si vous avez besoin d'en savoir plus sur le flags argument en Python, consultez mon tutoriel détaillé sur ce blog.

Le troisième exemple utilise le drapeau in-regex (?i) cela signifie aussi :"ignorer les majuscules".

Comment trouver toutes les occurrences d'un mot dans une chaîne ?

D'accord, vous n'êtes jamais satisfait, n'est-ce pas ? Explorons donc comment vous pouvez trouver toutes les occurrences d'un mot dans une chaîne.

Dans les exemples précédents, vous avez utilisé le re.search(pattern, string) méthode pour trouver la première correspondance du pattern dans le string .

Ensuite, vous apprendrez à trouver toutes les occurrences (pas seulement la première correspondance) en utilisant le re.findall(pattern, string) méthode.

💡 Tutoriel associé :Vous pouvez également lire le tutoriel de mon blog sur le findall() méthode qui explique tous les détails.

>>> import re
>>> re.findall('no', 'nononono')
['no', 'no', 'no', 'no']

Votre code récupère toutes les sous-chaînes correspondantes.

Si vous avez besoin de trouver tous les objets correspondants plutôt que les sous-chaînes correspondantes, vous pouvez utiliser le re.finditer(pattern, string) méthode :

>>> for match in re.finditer('no', 'nonononono'):
	print(match)

	
<re.Match object; span=(0, 2), match='no'>
<re.Match object; span=(2, 4), match='no'>
<re.Match object; span=(4, 6), match='no'>
<re.Match object; span=(6, 8), match='no'>
<re.Match object; span=(8, 10), match='no'>
>>> 

Le re.finditer(pattern, string) La méthode crée un itérateur qui itère sur toutes les correspondances et renvoie les objets de correspondance. De cette façon, vous pouvez trouver toutes les correspondances et obtenir également les objets correspondants.

Comment trouver toutes les lignes contenant un mot exact ?

Supposons que vous souhaitiez rechercher toutes les lignes contenant le mot '42' à partir d'une chaîne multiligne en Python. Comment avez-vous fait ?

La réponse utilise une fine spécialité de Python regex :la regex point correspond à tous les caractères, à l'exception du caractère de nouvelle ligne. Ainsi, la regex '.*' correspondra à tous les caractères d'une ligne donnée (mais s'arrêtera ensuite).

Voici comment vous pouvez utiliser ce fait pour obtenir toutes les lignes contenant un certain mot :

>>> import re
>>> s = '''the answer is 42
the answer: 42
42 is the answer
43 is not'''
>>> re.findall('.*42.*', s)
['the answer is 42', 'the answer: 42', '42 is the answer']

Trois lignes sur quatre contiennent le mot '42' . Le findall() la méthode les renvoie sous forme de chaînes.

Comment trouver toutes les lignes ne contenant pas un mot exact ?

Dans la section précédente, vous avez appris à trouver toutes les lignes contenant un mot exact.

Dans cette section, vous apprendrez à faire le contraire :trouver toutes les lignes qui ne contiennent PAS un mot exact.

C'est un peu plus compliqué. Je vais d'abord vous montrer le code et l'expliquer ensuite :

import re
s = '''the answer is 42
the answer: 42
42 is the answer
43 is not
the answer
42'''

for match in re.finditer('^((?!42).)*$', s, flags=re.M):
    print(match)

	
'''
<re.Match object; span=(49, 58), match='43 is not'>
<re.Match object; span=(59, 69), match='the answer'>
'''

Vous pouvez voir que le code correspond avec succès uniquement aux lignes qui ne contiennent pas la chaîne '42' .

Comment peux-tu le faire?

L'idée générale est de faire correspondre une ligne qui ne contient pas la chaîne '42' , imprimez-le sur le shell et passez à la ligne suivante. Le re.finditer(pattern, string) accomplit cela facilement en renvoyant un itérateur sur tous les objets de correspondance.

Le modèle regex '^((?!42).)*$' correspond à toute la ligne depuis la première position '^' à la dernière position '$' .

Tutoriel associé : Si vous avez besoin d'un rappel sur les métacaractères de début et de fin de ligne, lisez ce didacticiel de 5 minutes.

Entre les deux, vous faites correspondre un nombre arbitraire de caractères :le quantificateur astérisque le fait pour vous.

Tutoriel associé : Si vous avez besoin d'aide pour comprendre le quantificateur astérisque, consultez ce tutoriel de blog.

A quels personnages correspondez-vous ? Uniquement ceux où vous n'avez pas le mot négatif '42' dans votre anticipation.

Tutoriel associé : Si vous avez besoin d'un rappel sur les prévisions, consultez ce didacticiel.

Comme le lookahead lui-même ne consomme pas de caractère, nous devons le consommer manuellement en ajoutant le métacaractère point . qui correspond à tous les caractères sauf le caractère de saut de ligne '\n' .

Tutoriel associé : Il s'avère qu'il existe également un didacticiel de blog sur le métacaractère point.

Enfin, vous devez définir le re.MULTILINE drapeau, en bref :re.M , car il permet le démarrage ^ et fin $ métacaractères à faire correspondre également au début et à la fin de chaque ligne (pas seulement au début et à la fin de chaque chaîne).

Ensemble, cette expression régulière correspond à toutes les lignes qui ne contiennent pas le mot spécifique '42' .

Article connexe :

  • Python Regex Superpower – Le guide ultime