Токсизация слов с использованием регулярных выражений python

Я пытаюсь разделить строки на списки "тегов" в python. Разделение должно обрабатывать строки, такие как "HappyBirthday", и удалять большую пунктуацию, но сохранять дефисы и апострофы. Моя начальная точка:

tags = re.findall("([A-Z]{2,}(?=[A-Z]|$)|[A-Z][a-z]*)|\w+-\w+|[\w']+"

Я хотел бы повернуть эти образцы данных:

Jeff dog is un-American SomeTimes! BUT NOTAlways

В:

['Jeff's', 'dog', 'is', 'un-American', 'Some', 'Times', 'BUT', 'NOT', 'Always']

P.S. Мне жаль, что мое описание не очень хорошее. Я не уверен, как это объяснить, и в большинстве случаев у вас не получается с Google. Я надеюсь, что пример иллюстрирует это правильно.

Изменить: я думаю, мне нужно быть более точным, так что,

  • Если слово загипнотизировано и капитал, например, "ООН-Американец", он сохранит его как одно слово, поэтому выход будет "UN-American"
  • Если дефис имеет пространство на одной или обеих сторонах, a la 'THIS- is' или 'This - is', он должен игнорировать hypen и производить [ "THIS", "is" ] и ["THIS", "есть" ] уважительно,
  • и просто для апострофа, если его в середине слова, такого как "What's IsTalled", он должен произвести [ "Что есть", "Это", "Вызывается" ]

Ответ 1

Я предлагаю следующее:

re.findall("[A-Z]{2,}(?![a-z])|[A-Z][a-z]+(?=[A-Z])|[\'\w\-]+",s)

Это дает для вашего примера:

["Jeff's", 'dog', 'is', 'un-American', 'Some', 'Times', 'BUT', 'NOT', 'Always']

Объяснение: RegExp состоит из 3 альтернатив:

  • [A-Z]{2,}(?![a-z]) соответствует словам со всеми буквами
  • [A-Z][a-z]+(?=[A-Z]) соответствует словам с первым письмом. Внешний вид (?=[A-Z]) останавливает совпадение перед следующей заглавной буквой
  • [\'\w\-]+ соответствует всем остальным, то есть словам, которые могут содержать ' и -.

Ответ 2

Чтобы обрабатывать ваши отредактированные случаи, я бы изменил phynfo (+1) отличный ответ на

>>> s = """Jeff UN-American Un-American un-American 
           SomeTimes! BUT NOTAlways This- THIS- 
           What'sItCalled someTimes"""
>>> re.findall("[A-Z\-\']{2,}(?![a-z])|[A-Z\-\'][a-z\-\']+(?=[A-Z])|[\'\w\-]+",s)
["Jeff's", 'UN-', 'American', 'Un-', 'American', 'un-American', 
 'Some', 'Times', 'BUT', 'NOT', 'Always', 'This-', 'THIS-', 
 "What's", 'It', 'Called' 'someTimes']

Вам нужно четко определить правила для вашего желаемого поведения. Токенизация не является определением, вы должны иметь что-то подобное правилам phynfo. Например, у вас есть правило, что 'NOTAlways' должно перейти к 'NOT' и 'Always', и что дефисы должны быть сохранены. Таким образом, 'UN-American' разделяется, подобно тому, как UNAmerican будет разделен. Вы можете попробовать определить дополнительные правила, но вам нужно четко указать, какое правило применяется при перекрытии правил.