#python #regex #filter #selection
Вопрос:
У меня возникли проблемы с поиском правильного регулярного выражения для приведенного ниже сценария:
Давайте скажем:
a = "this is a sample"
Я хочу сопоставить целое слово — например, совпадение "hi"
должно возвращать значение False, так "hi"
как это не слово, и "is"
должно возвращать значение True, так как слева и справа нет альфа-символа.
Комментарии:
1. Я снова открыл этот вопрос, потому что он был закрыт как дубликат с неправильным сообщением.
Ответ №1:
Попробуй
re.search(r'bisb', your_string)
Из документов:
b Соответствует пустой строке, но только в начале или конце слова.
Обратите внимание, что re
модуль использует наивное определение «слова» как «последовательности буквенно-цифровых символов или символов подчеркивания», где «буквенно-цифровой» зависит от локали или параметров юникода.
Также обратите внимание, что без префикса необработанной строки b
отображается как «backspace» вместо границы слова регулярного выражения.
Комментарии:
1. Спасибо, я добавил флаги=re. ИГНОРИРОВАНИЕ
2. для чего нужен r в этом операторе — повторный поиск( r ‘bisb’, your_string) ?
3. @user2161049:
test!
это не слово, по любому определению, которое я знаю. Интересно, что это действительно работает для сокращений:re.search(r"bisn'tb", "it isn't bad")
возвращает совпадение.4. Как ни странно, это не работает для терминалов:
re.search(r"bisn'b", "it isn' bad")
не возвращает совпадения. Особенным является не апостроф, а расположение. Слово (шаблон) может иметь знак препинания внутри, но не в конце или начале.test!a
может соответствовать чему-то, ноtest!
не может.5. Почему я получил
x08
вместоb
этого ?
Ответ №2:
Попробуйте использовать класс символов «граница слова» в модуле регулярных выражений, re
:
x="this is a sample"
y="this isis a sample."
regex=re.compile(r"bisb") # For ignore case: re.compile(r"bisb", re.IGNORECASE)
regex.findall(y)
[]
regex.findall(x)
['is']
Из документации re.search()
.
b
соответствует пустой строке, но только в начале или конце слова…
Например
r'bfoob'
, совпадения'foo'
,'foo.'
,'(foo)'
,'bar foo baz'
но не'foobar'
или'foo3'
Ответ №3:
Я думаю, что поведение, желаемое ОП, не было полностью достигнуто с помощью данных ответов. В частности, желаемый вывод логического значения не был выполнен. Приведенные ответы действительно помогают проиллюстрировать концепцию, и я думаю, что они превосходны. Возможно, я могу проиллюстрировать то, что я имею в виду, заявив, что я думаю, что ОП использовала примеры, использованные из-за следующего.
Приведенная строка была,
a = "this is a sample"
Затем ОП заявил,
Я хочу сопоставить целое слово — например, совпадение
"hi"
должно возвращатьсяFalse
, так"hi"
как это не слово …
Как я понимаю, ссылка относится к маркеру поиска, "hi"
как он содержится в слове, "this"
. Если кто-то будет искать в строке a
слово "hi"
, оно должно быть получено False
в качестве ответа.
Операция продолжается,
… и
"is"
должен вернутьсяTrue
, так как слева и справа нет альфа-символа.
В этом случае ссылка относится к маркеру поиска "is"
, поскольку он находится в слове "is"
. Я надеюсь, что это поможет прояснить вопрос о том, почему мы используем границы слов. Другие ответы ведут себя так: «не возвращайте слово, если это слово не найдено само по себе, а не внутри других слов». Класс сокращенных символов «граница слов» прекрасно справляется с этой задачей.
"is"
До этого момента в примерах использовалось только это слово. Я думаю, что эти ответы верны, но я думаю, что есть еще один фундаментальный смысл вопроса, который необходимо рассмотреть. Чтобы понять концепцию, следует обратить внимание на поведение других строк поиска. Другими словами, нам нужно обобщить (отличный) ответ @georg, используя re.match(r"bisb", your_string)
Та же r"bisb"
концепция также используется в ответе @OmPrakash, который начал обобщающее обсуждение, показав
>>> y="this isis a sample." >>> regex=re.compile(r"bisb") # For ignore case: re.compile(r"bisb", re.IGNORECASE) >>> regex.findall(y) []
Допустим, метод, который должен демонстрировать поведение, которое я обсуждал, называется
find_only_whole_word(search_string, input_string)
Тогда следует ожидать следующего поведения.
>>> a = "this is a sample"
>>> find_only_whole_word("hi", a)
False
>>> find_only_whole_word("is", a)
True
Еще раз, вот как я понимаю вопрос ОП. У нас есть шаг к такому поведению с ответом от @georg , но его немного сложно интерпретировать/реализовать. а именно
>>> import re
>>> a = "this is a sample"
>>> re.search(r"bisb", a)
<_sre.SRE_Match object; span=(5, 7), match='is'>
>>> re.search(r"bhib", a)
>>>
Из второй команды нет выходных данных. Полезный ответ от @OmPrakesh показывает результат, но не True
или False
.
Вот более полная выборка ожидаемого поведения.
>>> 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
>>>
Это может быть достигнуто с помощью следующего кода:
#!/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)
Далее следует простая демонстрация. Запустите интерпретатор Python из того же каталога, в котором вы сохранили файл, 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
>>>
Комментарии:
1. Обратите внимание, что, если требуются только «истинные» целые слова, входные данные должны быть очищены.
>>> find_only_whole_word("another sentence", "To show this, I will use another sentence.")
ВОЗВРАТTrue
. Возможно, это желаемое поведение, поэтому я оставляю свой ответ как есть.2. Если вы хотите однострочный, используя
findall
метод, используемый @OsPrakesh:>>> len(re.findall(r"bhib", "This IS a sample.", flags=re.IGNORECASE))
возвращаетFalse
. Любые другие нужные строки могут быть вставлены междуb
буквами s.
Ответ №4:
Проблема с регулярным выражением заключается в том, что если строка, которую вы хотите найти в другой строке, содержит символы регулярного выражения, это усложняется. любая строка со скобками завершится ошибкой.
Этот код позволит найти слово
word="is"
srchedStr="this is a sample"
if srchedStr.find(" " word " ") >=0 or
srchedStr.endswith(" " word):
<do stuff>
Первая часть условного поиска текста с пробелом с каждой стороны, а вторая часть улавливает ситуацию конца строки. Обратите внимание, что конец является логическим, в то find
время как возвращает целое число
Комментарии:
1. Кроме того, я вижу, что уже был принят ответ — возможно, вы захотите удалить свой ответ и восстановить репутацию из-за пониженного голоса.
2. @davejagoda восстановит ли удаление ответа его/ее репутацию?
3. @silentphoenix Я так считаю: meta.stackexchange.com/questions/5221/…
4. Первый абзац неверен. Целевая строка может содержать произвольное содержимое.
5. Это не сработает, если слово появляется в начале целевой строки. Это также предполагает, что слова всегда окружены пробелами, что в целом неверно.