Питонический способ вставлять пробел перед заглавными буквами, но не вставлять пробел между аббревиатурой - PullRequest
3 голосов
/ 28 мая 2019

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

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

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

Хотя этот ответ помогает мне не вставлять пробелы между аббревиатурами внутри текста, например «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'))

Это дает мне «Дейв АФК прямо сейчас! 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

Ответы [ 2 ]

1 голос
/ 28 мая 2019

Вы можете поменять местами замены, чтобы сначала вставить пробелы перед заглавными буквами, перед которыми стоят символы, отличные от заглавных букв и пробелов, а затем добавить пробел перед словами, начинающимися с 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> вставляет все совпадения в шаблон замены.

0 голосов
/ 28 мая 2019

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

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

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

 \1

Пояснение

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

Regex demo | Python demo

Например

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...