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

Я нашел ответ от Дэвида Андерхилла в этом посте:

Питонический способ вставить пробел перед заглавными буквами

Хотя этот ответ помогает мне не вставлять пробелы между аббревиатурами в тексте, например "DaveIsAFKRightNow! Cool"

Но он обязательно вставляет пробел между V и P в «VP».

У меня только 25 очков опыта, и я не могу комментировать существующее сообщение, у меня нет другого выбора, кроме как создать еще одно сообщение для решения подобной проблемы.

Я не так хорош в RegEx и не могу понять, как справиться с этой ситуацией.

Я пробовал это:

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'))

Это дает мне «Дейв АФК прямо сейчас! Прохладно'

Мой текстовый пример такой:

General Manager or VP Torrance, CARequired education

Я хочу вывод как: General Manager or VP Torrance, CA Required education

Вывод, который я получаю: General Manager or V P Torrance, CA Required education

3
Vaibhav Rathi 28 Май 2019 в 16:02

2 ответа

Лучший ответ

Вы можете поменять местами замены, чтобы сначала вставить пробелы перед заглавными буквами, которым предшествуют символы, отличные от заглавных букв и пробелов, а затем добавить пробел перед словами, начинающимися с 1+ заглавными буквами, за которыми следуют прописные и строчные буквы:

import re
re_outer = re.compile(r'([^A-Z ])([A-Z])')
re_inner = re.compile(r'\b[A-Z]+(?=[A-Z][a-z])')
print(re_inner.sub(r'\g<0> ', re_outer.sub(r'\1 \2', 'DaveIsAFKRightNow!Cool')))
# => Dave Is AFK Right Now! Cool
print(re_inner.sub(r'\g<0> ', re_outer.sub(r'\1 \2', 'General Manager or VP Torrance, CARequired education'))) 
# => General Manager or VP Torrance, CA Required education

См. демонстрацию Python

\b[A-Z]+(?=[A-Z][a-z]) регулярное выражение соответствует

  • \b - граница слова
  • [A-Z]+ - 1+ заглавные буквы, которые
  • (?=[A-Z][a-z]) - сопровождается заглавной буквой и строчной буквой.

Обратите внимание, что \g<0> вставляет все совпадения в шаблон замены.

1
Wiktor Stribiżew 28 Май 2019 в 14:07

В качестве альтернативы вы можете использовать один шаблон с чередованием:

((?<=[^\W[A-Z])[A-Z]|(?<=\S)[A-Z](?=[a-z]))

В замене используйте пробел, за которым следует группа 1:

 \1

Объяснение

  • ( Группа захвата < UL>
  • (?<= Позитивный взгляд, утверждаю, что справа < UL>
  • [^\W[A-Z] Соответствует символу слова, кроме A-Z
  • ) Закрыть позитивный взгляд
  • | или
  • (?<=\S) Позитивный взгляд сзади, утверждают, что слева находится
  • [A-Z] Соответствует A-Z
  • (?=[a-z]) Позитивный взгляд, утверждаем, что справа - a-z
  • ) Закрыть группу захвата
  • Regex demo | демонстрация Python

    Например

    import re
    
    strings = [
        "General Manager or VP Torrance, CARequired education",
        "WordWordWord",
        "DaveIsAFKRightNow!Cool"
    ]
    pattern = re.compile(r'((?<=[^\W[A-Z])[A-Z]|(?<=\S)[A-Z](?=[a-z]))')
    
    for str in strings:
        print(pattern.sub(r' \1', str)) 
    

    Результат

    General Manager or VP Torrance, CA Required education
    Word Word Word
    Dave Is AFK Right Now! Cool
    
    0
    The fourth bird 28 Май 2019 в 13:51
    56342930