Регулярное выражение, соответствующее пунктуации на границе слова, включая подчеркивание - PullRequest
1 голос
/ 18 мая 2019

Я ищу регулярное выражение Python для переменной фразы со следующими свойствами: (Для примера, давайте предположим, что здесь переменная фраза принимает значение and. Но обратите внимание, что мне нужно сделать это вспособ, которым вещь, играющую роль and, может быть передана как переменная, которую я назову phrase.)

Должно совпадать: this_and, this.and, (and), [and], and^, ;And и т. Д.

Не должно совпадать: land, andy

Это то, что я пробовал до сих пор (где играет phraseроль and):

pattern = r"\b  " + re.escape(phrase.lower()) + r"\b"            

Кажется, это работает для всех моих требований, за исключением того, что оно не соответствует словам с подчеркиванием, например \_hello, hello\_, hello_world.

Редактировать: В идеале я хотел бы использовать стандартный модуль re библиотеки, а не какие-либо внешние пакеты.

Ответы [ 2 ]

1 голос
/ 18 мая 2019

Вот регулярное выражение, которое может решить эту проблему:

Regex

(?<=[\W_]+|^)and(?=[\W_]+|$)

Пример

# import regex

string = 'this_And'
test = regex.search(r'(?<=[\W_]+|^)and(?=[\W_]+|$)', string.lower())
print(test.group(0))
# prints 'and'

# No match
string = 'Andy'
test = regex.search(r'(?<=[\W_]+|^)and(?=[\W_]+|$)', string.lower())
print(test)
# prints None

strings = [ "this_and", "this.and", "(and)", "[and]", "and^", ";And"]
[regex.search(r'(?<=[\W_]+|^)and(?=[\W_]+|$)', s.lower()).group(0) for s in strings if regex.search(r'(?<=[\W_]+|^)and(?=[\W_]+|$)', s.lower())]
# prints ['and', 'and', 'and', 'and', 'and', 'and']

Объяснение

[\W_]+ означает, что мы принимаем до (?<=) или после (?=) and только несловарные символы, кроме знака подчеркивания _ (символ слова, который) принимается. |^ и |$ позволяют совпадениям лежать на краю строки.

Редактировать

Как уже упоминалось в моем комментарии, модуль regex не дает ошибок с переменной длиной взгляда (в отличие от re).

# This works fine
# import regex
word = 'and'
pattern = r'(?<=[\W_]+|^){}(?=[\W_]+|$)'.format(word.lower())
string = 'this_And'
regex.search(pattern, string.lower())

Однако, если вы настаиваете на использовании re, то в верхней части моей головы я бы посоветовал разделить взгляд сзади на два (?<=[\W_])and(?=[\W_]+|$)|^and(?=[\W_]+|$), чтобы также регистрировались случаи, когда строка начинается с and.

# This also works fine
# import re
word = 'and'
pattern = r'(?<=[\W_]){}(?=[\W_]+|$)|^{}(?=[\W_]+|$)'.format(word.lower(), word.lower())
string = 'this_And'
re.search(pattern, string.lower())
0 голосов
/ 26 мая 2019

Вы можете использовать

r'(?<![^\W_])and(?![^\W_])'

См. Демоверсию regex .Скомпилируйте с флагом re.I, чтобы разрешить сопоставление без учета регистра.

Подробности

  • (?<![^\W_]) - предыдущий символ не должен быть буквенным или цифровым символом
  • and - какое-то ключевое слово
  • (?![^\W_]) - следующий символ не может быть буквой или цифрой

Python demo :

import re
strs = ['this_and', 'this.and', '(and)', '[and]', 'and^', ';And', 'land', 'andy']
phrase = "and"
rx = re.compile(r'(?<![^\W_]){}(?![^\W_])'.format(re.escape(phrase)), re.I)
for s in strs:
    print("{}: {}".format(s, bool(rx.search(s))))

Выход:

this_and: True
this.and: True
(and): True
[and]: True
and^: True
;And: True
land: False
andy: False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...