Питонический способ вставить пробел перед заглавными буквами - PullRequest
20 голосов
/ 14 октября 2008

У меня есть файл, формат которого я изменяю с помощью скрипта Python. У меня есть несколько строк в верблюжьей оболочке в этом файле, где я просто хочу вставить один пробел перед заглавной буквой, поэтому «WordWordWord» становится «Word Word Word».

Мой ограниченный опыт регулярных выражений только что остановился у меня - кто-то может придумать приличное регулярное выражение, чтобы сделать это, или (еще лучше), есть ли более питонический способ сделать это, что я пропускаю?

Ответы [ 9 ]

33 голосов
/ 14 октября 2008

Вы можете попробовать:

>>> re.sub(r"(\w)([A-Z])", r"\1 \2", "WordWordWord")
'Word Word Word'
26 голосов
/ 14 октября 2008

Если есть последовательные заглавные буквы, то результат Грегса может не то, что вы ищете, так как \ w потребляет символ перед заглавной буквой, подлежащей замене.

>>> 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'
10 голосов
/ 14 октября 2008

Возможно, короче:

>>> re.sub(r"\B([A-Z])", r" \1", "DoIThinkThisIsABetterAnswer?")
4 голосов
/ 20 августа 2017

Может быть, вас заинтересует однострочная реализация без использования regexp:

''.join(' ' + char if char.isupper() else char.strip() for char in text).strip()
4 голосов
/ 14 октября 2008

С помощью регулярных выражений вы можете сделать это:

re.sub('([A-Z])', r' \1', str)

Конечно, это будет работать только для символов ASCII, если вы хотите использовать Unicode, это совершенно новая банка червей: -)

2 голосов
/ 16 октября 2017

Если у вас есть сокращения, вы, вероятно, не хотите пробелов между ними. Это двухэтапное регулярное выражение сохранит аббревиатуры нетронутыми (а также будет рассматривать знаки препинания и другие не прописные буквы как нечто для добавления пробела):

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'

0 голосов
/ 14 октября 2008

Я думаю, что регулярные выражения - это то, что нужно, но просто для того, чтобы дать чистую версию на Python без (надеюсь) проблем, на которые указал ΤΖΩΤΖΙΟΥ:

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()
0 голосов
/ 14 октября 2008

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

Как насчет:

text = 'WordWordWord'
new_text = ''

for i, letter in enumerate(text):
    if i and letter.isupper():
        new_text += ' '

    new_text += letter
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...