Haga coincidir una palabra completa en una cadena usando expresiones regulares dinámicas

Resuelto kyrenia asked hace 9 años • 1 respuestas

Estoy buscando ver si una palabra aparece en una oración usando expresiones regulares. Las palabras están separadas por espacios, pero pueden tener puntuación en ambos lados. Si la palabra está en el medio de la cadena, la siguiente coincidencia funciona (evita la coincidencia de palabras parciales y permite la puntuación en ambos lados de la palabra).

match_middle_words = " [^a-zA-Z\d ]{0,}" + word + "[^a-zA-Z\d ]{0,} "

Sin embargo, esto no coincidirá con la primera ni la última palabra, ya que no hay espacios al final o al principio. Entonces, para estos casos, también he estado usando:

match_starting_word = "^[^a-zA-Z\d]{0,}" + word + "[^a-zA-Z\d ]{0,} "
match_end_word = " [^a-zA-Z\d ]{0,}" + word + "[^a-zA-Z\d]{0,}$"

y luego combinando con

 match_string = match_middle_words  + "|" + match_starting_word  +"|" + match_end_word 

¿Existe una forma sencilla de evitar la necesidad de tres términos coincidentes? Específicamente, ¿hay alguna forma de especificar un espacio o el inicio del archivo (es decir, "^") y algo similar, ya sea un espacio o el final del archivo (es decir, "$")?

kyrenia avatar May 02 '15 05:05 kyrenia
Aceptado

¿ Por qué no utilizar un límite de palabras ?

match_string = r'\b' + word + r'\b'
match_string = r'\b{}\b'.format(word)
match_string = rf'\b{word}\b'          # Python 3.7+ required

Si tiene una lista de palabras (digamos, en una wordsvariable) que deben coincidir como una palabra completa, use

match_string = r'\b(?:{})\b'.format('|'.join(words))
match_string = rf'\b(?:{"|".join(words)})\b'         # Python 3.7+ required

En este caso, se asegurará de que la palabra solo se capture cuando esté rodeada de caracteres que no sean palabras. También tenga en cuenta que \bcoincide al principio y al final de la cadena. Entonces, no sirve de nada agregar 3 alternativas.

Código de muestra :

import re
strn = "word hereword word, there word"
search = "word"
print re.findall(r"\b" + search + r"\b", strn)

Y encontramos nuestras 3 coincidencias:

['word', 'word', 'word']

NOTA SOBRE LOS LÍMITES DE LAS "PALABRAS"

Cuando las "palabras" son en realidad fragmentos de caracteres, debe re.escapehacerlos antes de pasar al patrón de expresiones regulares:

match_string = r'\b{}\b'.format(re.escape(word)) # a single escaped "word" string passed
match_string = r'\b(?:{})\b'.format("|".join(map(re.escape, words))) # words list is escaped
match_string = rf'\b(?:{"|".join(map(re.escape, words))})\b' # Same as above for Python 3.7+

Si las palabras que van a coincidir como palabras completas pueden comenzar o terminar con caracteres especiales, \b no funcionarán , utilice límites de palabras inequívocos :

match_string = r'(?<!\w){}(?!\w)'.format(re.escape(word))
match_string = r'(?<!\w)(?:{})(?!\w)'.format("|".join(map(re.escape, words))) 

Si los límites de las palabras son caracteres de espacio en blanco o el inicio/final de una cadena, utilice límites de espacio en blanco :(?<!\S)...(?!\S)

match_string = r'(?<!\S){}(?!\S)'.format(word)
match_string = r'(?<!\S)(?:{})(?!\S)'.format("|".join(map(re.escape, words))) 
Wiktor Stribiżew avatar May 01 '2015 22:05 Wiktor Stribiżew