Разделить верхний регистр и UpperCamelCase на отдельные слова

#python #regex

#python #регулярное выражение

Вопрос:

То, что я пытаюсь сделать, это разделить строки UpperCamelCase и UpperCamelCase на разные слова. У нас есть соглашение об именовании, в котором сокращения пишутся в ВЕРХНЕМ РЕГИСТРЕ, если в начале.

Например. SFTPServer

Чего я пытаюсь достичь, так это разделить это на два слова SFTP и Server

Для UpperCamelCase я смог использовать следующий фрагмент кода

 r="SftpServer"
print(' '.join(re.findall('^[a-z] |[A-Z][^A-Z]*', r)))
  

Выводит:

 Sftp Server
  

Вопрос: Есть ли какой-нибудь способ настроить это регулярное выражение так, чтобы я получал выходные данные для обоих случаев

т.е. SFTPServer и SftpServer ?

Я также упомяну свой вариант использования, поскольку это может дополнительно дать некоторое представление о вопросе. Я пытаюсь преобразовать имена столбцов в метки в flask и SQL Server.

 def get_label_names():
        cursor=CONN.cursor()
        db_name=CONFIG['DB']['DATABASE']['NAME']
        cursor.execute('use ' db_name)
        cursor.execute(f"""
        SELECT COLUMN_NAME
        FROM {db_name}.INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_NAME = N'Client'
        """
        )
        col_info=[item[0] for item in cursor.fetchall()]
        labels=[' '.join(re.findall('^[a-z] |[A-Z][^A-Z]*', r)) for r in col_info]
        return labels
  

Ответ №1:

Наш лучший вариант здесь, вероятно, re.findall , потому что он позволяет использовать предварительные просмотры, в то время как re.split этого не делает. Мы можем попробовать разделить по следующему шаблону:

 [A-Z]{2,}(?=[A-Z][a-z])|[A-Z][a-z] |[A-Z] $
  

Этот шаблон говорит о соответствии:

 [A-Z]{2,}(?=[A-Z][a-z])
  

Две или более заглавных буквы, пока не будет достигнута заглавная, за которой следует строчная (указывающая начало следующего слова camelcase).

 [A-Z][a-z] 
  

Слово в формате camelcase, обозначаемое прописной буквой, за которой следует одна или несколько строчных букв.

 [A-Z] $
  

Любое количество заглавных букв терминала подряд.

Код:

 input = "SFTPServerABC"
results = re.findall(r'[A-Z]{2,}(?=[A-Z][a-z])|[A-Z][a-z] |[A-Z] $', input)
print(results)

['SFTP', 'Server', 'ABC']