web-dev-qa-db-fra.com

L'expression rationnelle Python correspond au mot entier

Je ne parviens pas à trouver la bonne expression régulière pour le scénario ci-dessous:

Disons:

a = "this is a sample"

Je veux faire correspondre tout le mot - par exemple, "hi" doit renvoyer False puisque "hi" n'est pas un mot et "is" devrait renvoyer True car il n'y a pas de caractère alpha à gauche et à droite.

27
user2161049

Essayer

re.search(r'\bis\b', your_string)

De les docs :

\ b Correspond à la chaîne vide, mais uniquement au début ou à la fin d'un mot. 

Notez que le module re utilise une définition naïve de "Word" en tant que "séquence de caractères alphanumériques ou de soulignement", où "alphanumérique" dépend des options de localisation ou Unicode.

Notez également que sans le préfixe de chaîne brute, \b est considéré comme un "retour arrière" au lieu de la limite de mot regex.

34
georg

Essayez d’utiliser la classe de caractères "Limite de mot" dans le module regex, re:

x="this is a sample"
y="this isis a sample."
regex=re.compile(r"\bis\b")  # For ignore case: re.compile(r"\bis\b", re.IGNORECASE)

regex.findall(y)
[]

regex.findall(x)
['is']

De la documentation de re.search() .

\b correspond à la chaîne vide, mais uniquement au début ou à la fin d'un mot

...

Par exemple, r'\bfoo\b' correspond à 'foo', 'foo.', '(foo)', 'bar foo baz' mais pas 'foobar' ni 'foo3'

2
Om Prakash

Je pense que le comportement souhaité par le PO n'a pas été complètement obtenu en utilisant les réponses données. Plus précisément, le résultat souhaité d'un booléen n'a pas été atteint. Les réponses données do aident à illustrer le concept et je les trouve excellentes. Je peux peut-être illustrer ce que je veux dire en déclarant que je pense que le PO a utilisé les exemples utilisés pour les raisons suivantes.

La chaîne donnée était, 

a = "this is a sample" 

Le PO a ensuite déclaré:

Je veux faire correspondre le mot entier - par exemple, la correspondance "hi" devrait renvoyer False puisque "hi" n'est pas un mot ...

Si j'ai bien compris, il s'agit du jeton de recherche, "hi", tel qu'il se trouve dans le mot, "this". Si quelqu'un devait rechercher dans la chaîne, a, le Word"hi", il devrait recevoir False comme réponse.

Le PO continue,

... et "is" devraient renvoyer True puisqu'il n'y a pas de caractère alpha à gauche et à droite.

Dans ce cas, la référence concerne le jeton de recherche "is" tel qu'il se trouve dans le mot "is". J'espère que cela aide à clarifier les raisons pour lesquelles nous utilisons les limites de Word. Les autres réponses ont le comportement suivant: "ne retourne pas un mot à moins que ce mot ne soit trouvé par lui-même - pas à l'intérieur d'autres mots." La "limite de mots" classe de caractères abrégée fait bien ce travail.

Jusqu'à présent, seul le mot "is" a été utilisé. Je pense que ces réponses sont correctes, mais je pense que la signification fondamentale de la question doit être abordée. Le comportement des autres chaînes de recherche doit être noté pour comprendre le concept. En d'autres termes, nous devons généraliser la (excellente) réponse de @georg à l'aide de re.match(r"\bis\b", your_string). Le même concept r"\bis\b" est également utilisé dans la réponse de @OmPrakash, qui a lancé la discussion de généralisation en montrant

>>> y="this isis a sample."
>>> regex=re.compile(r"\bis\b")  # For ignore case: re.compile(r"\bis\b", re.IGNORECASE)
>>> regex.findall(y)
[]

Disons que la méthode qui doit présenter le comportement dont j'ai parlé est nommée 

find_only_whole_Word(search_string, input_string)

Le comportement suivant devrait alors être attendu.

>>> a = "this is a sample"
>>> find_only_whole_Word("hi", a)
False
>>> find_only_whole_Word("is", a)
True

Encore une fois, voici comment je comprends la question du PO. La réponse de @georg est un pas en avant vers ce comportement, mais il est un peu difficile à interpréter/à mettre en œuvre. en être témoin

>>> import re
>>> a = "this is a sample"
>>> re.search(r"\bis\b", a)
<_sre.SRE_Match object; span=(5, 7), match='is'>
>>> re.search(r"\bhi\b", a)
>>>

Il n'y a pas de sortie de la deuxième commande. La réponse utile de @OmPrakesh affiche le résultat, mais pas True ni False.

Voici un échantillonnage plus complet du comportement à prévoir.

>>> find_only_whole_Word("this", a)
True
>>> find_only_whole_Word("is", a)
True
>>> find_only_whole_Word("a", a)
True
>>> find_only_whole_Word("sample", a)
True
# Use "ample", part of the Word, "sample": (s)ample
>>> find_only_whole_Word("ample", a)
False
# (t)his
>>> find_only_whole_Word("his", a)
False
# (sa)mpl(e)
>>> find_only_whole_Word("mpl", a)
False
# Any random Word
>>> find_only_whole_Word("applesauce", a)
False
>>>

Ceci peut être accompli avec le code suivant:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
#@file find_only_whole_Word.py

import re

def find_only_whole_Word(search_string, input_string):
  # Create a raw string with Word boundaries from the user's input_string
  raw_search_string = r"\b" + search_string + r"\b"

  match_output = re.search(raw_search_string, input_string)
  ##As noted by @OmPrakesh, if you want to ignore case, uncomment
  ##the next two lines
  #match_output = re.search(raw_search_string, input_string, 
  #                         flags=re.IGNORECASE)

  no_match_was_found = ( match_output is None )
  if no_match_was_found:
    return False
  else:
    return True

##endof:  find_only_whole_Word(search_string, input_string)

Une démonstration simple suit. Exécutez l'interpréteur Python à partir du même répertoire que celui où vous avez enregistré le fichier, find_only_whole_Word.py.

>>> from find_only_whole_Word import find_only_whole_Word
>>> a = "this is a sample"
>>> find_only_whole_Word("hi", a)
False
>>> find_only_whole_Word("is", a)
True
>>> find_only_whole_Word("cucumber", a)
False
# The excellent example from @OmPrakash
>>> find_only_whole_Word("is", "this isis a sample")
False
>>>
0
bballdave025