Вопрос-Ответ

Match a whole word in a string using dynamic regex

Сопоставление целого слова в строке с помощью динамического регулярного выражения

Я хочу посмотреть, встречается ли слово в предложении с помощью регулярного выражения. Слова разделяются пробелами, но могут иметь знаки препинания с обеих сторон. Если слово находится в середине строки, работает следующее сопоставление (оно предотвращает совпадение частей слова, разрешает знаки препинания по обе стороны от слова).

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

Однако это не будет соответствовать первому или последнему слову, поскольку в нем нет конечного / переднего пробела. Итак, для этих случаев я также использовал:

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,}$"

а затем объединение с

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

Есть ли простой способ избежать необходимости в трех терминах сопоставления? В частности, есть ли способ указать 'через пробел или начало файла (т.Е. "^") и тому подобное", либо пробел, либо конец файла (т.Е. "$")?

Переведено автоматически
Ответ 1

Почему бы не использовать границу слова?

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

Если у вас есть список слов (скажем, в words переменной), который нужно сопоставить как целое слово, используйте

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

В этом случае вы убедитесь, что слово записывается только тогда, когда оно окружено несловесными символами. Также обратите внимание, что \b совпадает в начале и конце строки. Итак, нет смысла добавлять 3 альтернативы.

Пример кода:

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

И мы нашли 3 наших совпадения:

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

ОБРАТИТЕ ВНИМАНИЕ НА ГРАНИЦЫ "WORD"

Когда "слова" на самом деле являются фрагментами любых символов, вы должны re.escape использовать их перед переходом к шаблону регулярных выражений:

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+

Если слова, которые должны быть сопоставлены как целые слова, могут начинаться / заканчиваться специальными символами, \b не сработает, используйте однозначные границы слов:

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

Если границами слов являются символы пробела или начало / конец строки, используйте границы пробела, (?<!\S)...(?!\S):

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