Регулярное выражение в случае с верблюдом

Почти там, но я нашел пару дыр с моим регулярным выражением, чтобы превратить CamelCase в дело с разнесенным предложением. Он хорошо работает в большинстве случаев (каламбур), но зацикливается на первом слове с переносами. Я не могу понять, почему.

import re

# ---------------------------------------------------------
def camelCaseToSpacedTitleCase(u):
  # add spaces
  regex = re.sub("(.)([A-Z][a-z-]+)", r"\1 \2", u)

  # make title case
  regex = re.sub("([a-z0-9])([A-Z])", r"\1 \2", regex)

  # keep CAPITALISED words
  regex = re.sub("(^|\s)(\S)", r"\1" + r"\2".upper(), regex)

  # keep Mc and Mac
  regex = re.sub("(Mc|Mac)(\s)", r"\1", regex)

  # keep digits
  regex = re.sub("([a-z]+)([0-9]+\s)", r"\1 \2", regex)

  # keep I or A
  regex = re.sub("(\sA|\sI)([A-Z])([a-z]*)", r"\1 \2\3", regex)

  # remove double whitespaces
  regex = re.sub("\s{2,32}", r" ", regex)

  return regex


test1 = "TheAmazingSpider-Man"
test2 = "WeAreSexBob-Omb"
test3 = "SR-128  SomethingSomething"
test4 = "Ex-Voto - Monitor"
test5 = "FergusMcNeilEyeContact"
test6 = "It'sABanana"
test7 = "HouseOf1000Zombies!"

print (camelCaseToSpacedTitleCase(test1))
print (camelCaseToSpacedTitleCase(test2))
print (camelCaseToSpacedTitleCase(test3))
print (camelCaseToSpacedTitleCase(test4))
print (camelCaseToSpacedTitleCase(test5))
print (camelCaseToSpacedTitleCase(test6))
print (camelCaseToSpacedTitleCase(test7))

Я бы ожидал увидеть

"The Amazing Spider-Man" 
"We Are Sex Bob-Omb"
"SR-128 Something Something"
"Ex-Voto - Monitor"
"Fergus McNeil Eye Contact"
"It's A Banana"
"House Of 1000 Zombies!"

Я хочу избежать использования.titlecase() по причинам, указанным выше

1 ответ

Этот тип обработки может быть сложным. Я думаю, что проблема, которую вы видите, заключается в первом шаге, когда вы впервые добавляете пробелы. Вместо добавления пробела к любому разделению верблюда, применяйте его, только если перед разделением не стоит дефис.

# Replace: regex = re.sub("(.)([A-Z][a-z-]+)", r"\1 \2", u)
regex = re.sub("([^-])([A-Z][a-z-]+)", r"\1 \2", u)

Дает следующие результаты...

# The Amazing Spider-Man
# We Are Sex Bob-Omb
# SR-128 Something Something
# Ex-Voto - Monitor
# Fergus McNeil Eye Contact
# It's A Banana
# House Of 1000 Zombies!
Другие вопросы по тегам