#python #regex
#python #регулярное выражение
Вопрос:
Я пытаюсь удалить все знаки препинания и все, что находится внутри скобок, из строки в python. Идея состоит в том, чтобы несколько нормализовать названия песен, чтобы получить лучшие результаты при запросе веб-сервиса MusicBrainz.
Пример ввода: T.N.T. (live) [nyc]
Ожидаемый результат: T N T
Я могу сделать это в двух регулярных выражениях, но я хотел бы посмотреть, можно ли это сделать только в одном. Я попробовал следующее, которое не сработало…
>>> re.sub(r'[.*?]|(.*?)|W ', ' ', 'T.N.T. (live) [nyc]')
'T N T live nyc '
Если я разделю W
на его собственное регулярное выражение и выполню его вторым, я получу ожидаемый результат, поэтому кажется, что W
фигурные скобки и скобки в скобках используются до того, как с ними справятся первые два варианта.
Комментарии:
1. Вас беспокоят несогласованные скобки или несколько скобок одного типа (возможно, как часть оригинального названия)? Например, каким должен быть результат для входных данных
T.N.T. (live
(долженlive
остаться?) иT.N.T. (live) X (nyc)
(долженX
остаться)?2. На данный момент я не беспокоюсь о несопоставимых или вложенных скобках. Я думаю, что они, вероятно, не будут появляться достаточно часто, чтобы вызвать большую проблему.
Ответ №1:
Вы правы, что W
использует фигурные скобки, удалите
, и вы должны быть установлены:
>>> re.sub(r'[.*?]|(.*?)|W', ' ', 'T.N.T. (live) [nyc]')
'T N T '
Ответ №2:
Вот мини-анализатор, который делает то же самое, что я написал в качестве упражнения. Если ваши усилия по нормализации становятся намного сложнее, вы можете начать искать решения на основе синтаксического анализа. Это работает как крошечный синтаксический анализатор.
# Remove all non-word chars and anything between parens or brackets
def consume(I):
I = iter(I)
lookbehind = None
def killuntil(returnchar):
while True:
ch = I.next()
if ch == returnchar:
return
for i in I:
if i in 'abcdefghijklmnopqrstuvwyzABCDEFGHIJKLMNOPQRSTUVWXYZ':
yield i
lookbehind = i
elif not i.strip() and lookbehind != ' ':
yield ' '
lookbehind = ' '
elif i == '(':
killuntil(')')
elif i == '[':
killuntil(']')
elif lookbehind != ' ':
lookbehind = ' '
yield ' '
s = "T.N.T. (live) [nyc]"
c = consume(s)
Комментарии:
1. В качестве дополнительного примечания,
string.letters=='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
. Итакimport string
и сэкономьте время на вводе текста.
Ответ №3:
W
Использует квадратные скобки, потому что у него «есть запуск»: он начинает сопоставление с точки после второго T и совпадает до первой круглой скобки включительно: . (
. После этого он снова начинает сопоставление от скобки к скобке: ) [
.
Ответ №4:
W
Если флаги LOCALE и UNICODE не указаны, соответствует любому не алфавитно-цифровому символу; это эквивалентно набору [^a-zA-Z0-9_].
Так что попробуйте r'[.*?]|(.*?)|{.*?}|[^a-zA-Z0-9_()[]{}] '
.
Хотя решение Эндрю, вероятно, лучше.