Ответ 1
Вы можете попробовать:
>>> re.sub(r"(\w)([A-Z])", r"\1 \2", "WordWordWord")
'Word Word Word'
У меня есть файл, формат которого я изменяю через python script. У меня есть несколько верблюжьих строк в этом файле, где я просто хочу вставить одно пробел перед заглавной буквой, поэтому "WordWordWord" становится "Word Word Word".
Мой ограниченный опыт регулярного выражения просто остановился на мне - может ли кто-то подумать о приличном регулярном выражении, чтобы сделать это, или (еще лучше) есть ли более питонический способ сделать это, что мне не хватает?
Вы можете попробовать:
>>> re.sub(r"(\w)([A-Z])", r"\1 \2", "WordWordWord")
'Word Word Word'
Если есть последовательные капиталы, то результат Грегса может не то, что вы ищете, так как \w потребляет caracter перед заменяемым письмом.
>>> re.sub(r"(\w)([A-Z])", r"\1 \2", "WordWordWWWWWWWord")
'Word Word WW WW WW Word'
Взгляд поможет решить эту проблему:
>>> re.sub(r"(?<=\w)([A-Z])", r" \1", "WordWordWWWWWWWord")
'Word Word W W W W W W Word'
Возможно, короче:
>>> re.sub(r"\B([A-Z])", r" \1", "DoIThinkThisIsABetterAnswer?")
Взгляните на мой ответ на .NET. Как вы можете разделить строку с разделителями "caps" в массив?
Изменить: Возможно, лучше включить его здесь.
re.sub(r'([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-z]))', r'\1 ', text)
Например:
"SimpleHTTPServer" => ["Simple", "HTTP", "Server"]
С помощью регулярных выражений вы можете сделать это:
re.sub('([A-Z])', r' \1', str)
Конечно, это будет работать только для символов ASCII, если вы хотите сделать Unicode это совершенно новая возможность червей: -)
Возможно, вам будет интересна реализация с одним liner без использования regexp:
''.join(' ' + char if char.isupper() else char.strip() for char in text).strip()
Если у вас есть аббревиатуры, вам, вероятно, не нужны пробелы между ними. Это двухэтапное регулярное выражение будет содержать аббревиатуры без изменений (а также обрабатывать знаки препинания и другие буквы, отличные от прописных, как что-то, чтобы добавить пробел):
re_outer = re.compile(r'([^A-Z ])([A-Z])')
re_inner = re.compile(r'(?<!^)([A-Z])([^A-Z])')
re_outer.sub(r'\1 \2', re_inner.sub(r' \1\2', 'DaveIsAFKRightNow!Cool'))
Выход будет: 'Dave Is AFK Right Now! Cool'
Я согласен, что решение регулярных выражений является самым простым, но я бы не сказал, что это самый пифонический.
Как насчет:
text = 'WordWordWord'
new_text = ''
for i, letter in enumerate(text):
if i and letter.isupper():
new_text += ' '
new_text += letter
Я думаю, что регулярные выражения - это путь сюда, но просто для того, чтобы дать чистую версию python без (надеюсь) любой из проблем, которые TΖΩΤΖΙΟΥ указал:
def splitCaps(s):
result = []
for ch, next in window(s+" ", 2):
result.append(ch)
if next.isupper() and not ch.isspace():
result.append(' ')
return ''.join(result)
window() - это служебная функция, которую я использую для работы в скользящем окне элементов, которое определяется как:
import collections, itertools
def window(it, winsize, step=1):
it=iter(it) # Ensure we have an iterator
l=collections.deque(itertools.islice(it, winsize))
while 1: # Continue till StopIteration gets raised.
yield tuple(l)
for i in range(step):
l.append(it.next())
l.popleft()