Как преобразовать строку из формата CamelCase в понятное представление с пробелами в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В процессе разработки на платформе 1С программисты регулярно сталкиваются с необходимостью вывода технических наименований объектов в удобном для пользователя виде. Например, системное имя колонки или реквизита СведенияОВзносах на форме должно превратиться в красивое и легко читаемое "Сведения о взносах".

Такой формат написания идентификаторов без пробелов, где каждое новое слово начинается с заглавной буквы, называется CamelCase (или "верблюжий регистр"). В этой статье мы подробно разберем, как решить задачу автоматического преобразования таких строк в обычные предложения с пробелами. Мы рассмотрим несколько эффективных подходов: от классического посимвольного перебора, обсуждаемого на форумах, до современных решений с использованием регулярных выражений и словарей исключений.

Метод 1. Классический посимвольный перебор с анализом соседних символов

Давайте проанализируем самый очевидный и доступный на любых версиях платформы способ — посимвольный обход строки. Просто вставить пробел перед каждой заглавной буквой недостаточно, ведь в строке могут встретиться аббревиатуры (например, РасчетНДФЛ), которые превратятся в нечитаемое Расчет Н Д Ф Л.

Чтобы избежать этой проблемы, нам необходимо анализировать не только текущий символ, но также предыдущий и следующий. Рассмотрим оптимизированный алгоритм, предложенный участниками сообщества:


Функция ПреобразоватьСтрокуCamelCase(Знач ИсходнаяСтрока) Экспорт
    ДлинаСтроки = СтрДлина(ИсходнаяСтрока);
    Если ДлинаСтроки <= 1 Тогда
        Возврат ИсходнаяСтрока;
    КонецЕсли;
    
    // Инициализируем результирующую строку первым символом
    Рез = Лев(ИсходнаяСтрока, 1);
    ИсходнаяСтрока = Прав(ИсходнаяСтрока, ДлинаСтроки - 1);
    
    ПредыдущаяБуква = Рез;
    Для Индекс = 1 По ДлинаСтроки - 1 Цикл        
        Буква = Лев(ИсходнаяСтрока, 1);
        ИсходнаяСтрока = Прав(ИсходнаяСтрока, СтрДлина(ИсходнаяСтрока) - 1);
        СледующаяБуква = Лев(ИсходнаяСтрока, 1);
        
        // Проверяем, идет ли подряд группа заглавных букв (например, аббревиатура)
        Если Буква = ВРег(Буква) И ПредыдущаяБуква = ВРег(ПредыдущаяБуква) И СледующаяБуква = ВРег(СледующаяБуква) Тогда
            Рез = Лев(Рез, СтрДлина(Рез) - 1) + ВРег(ПредыдущаяБуква);
            Рез = Рез + ВРег(Буква);    
        ИначеЕсли Буква = ВРег(Буква) Тогда
            // Если буква заглавная, перед ней добавляем пробел, а саму букву переводим в нижний регистр
            Рез = Рез + " " + НРег(Буква);
        Иначе
            Рез = Рез + Буква;
        КонецЕсли;    
        
        ПредыдущаяБуква = Буква;
    КонецЦикла;    
    
    // Корректируем первую букву предложения, делая её заглавной
    Рез = ВРег(Лев(Рез, 1)) + Сред(Рез, 2);
    
    Возврат Рез;        
КонецФункции

Давайте подробно разберем, как работает этот код по шагам:

  1. Мы определяем общую длину исходного текста и сразу отсекаем пустые или состоящие из одного символа строки.
  2. Переменная Рез инициализируется первой буквой исходной строки, которая гарантированно останется заглавной.
  3. В цикле мы последовательно "откусываем" по одному символу с помощью функций Лев() и Прав().
  4. Условие Буква = ВРег(Буква) позволяет определить, является ли текущий символ заглавным.
  5. Если заглавные буквы идут подряд (например, НДФЛ), алгоритм сохраняет их регистр и не вставляет между ними пробелы.
  6. Если заглавная буква встречается после строчной, перед ней вставляется пробел, а сама она принудительно переводится в нижний регистр функции НРег() для придания строке естественного вида предложения.

Метод 2. Использование регулярных выражений (для платформ 1С версии 8.3.23 и выше)

Если в вашей конфигурации используется современная версия платформы 1С (начиная с релиза 8.3.23), то писать сложные и ресурсоемкие циклы посимвольного перебора больше нет необходимости. В платформу была добавлена нативная поддержка регулярных выражений.

Мы можем решить эту задачу буквально в одну строку, используя встроенную функцию СтрЗаменитьПоРегулярномуВыражению(). Давайте посмотрим, как выглядит такое изящное решение:


Функция ПреобразоватьСтрокуРегуляркой(Знач ИсходнаяСтрока) Экспорт
    // Шаблон ищет границы между строчными и заглавными буквами
    Шаблон = "([а-яё])([А-ЯЁ])";
    Результат = СтрЗаменитьПоРегулярномуВыражению(ИсходнаяСтрока, Шаблон, "$1 $2");
    
    // Переводим все слова кроме первого в нижний регистр
    // Для этого разобьем строку по пробелам, обработаем элементы и соберем обратно
    МассивСлов = СтрРазделить(Результат, " ", Ложь);
    Для Индекс = 1 По МассивСлов.В Граница() Цикл
        МассивСлов[Индекс] = НРег(МассивСлов[Индекс]);
    КонецЦикла;
    
    Возврат СтрСоединить(МассивСлов, " ");
КонецФункции

Выясним причину, почему этот способ предпочтительнее для новых разработок:

Метод 3. Продвинутый парсер со словарем исключений и поддержкой предлогов

Для достижения идеального результата (как в примере автора темы: СведенияОВзносах превращается в Сведения о взносах, а не Сведения О Взносах) стандартных алгоритмов недостаточно. Нам необходимо научить систему распознавать служебные части речи (предлоги, союзы) и принудительно оставлять их в нижнем регистре, а также корректно обрабатывать устоявшиеся аббревиатуры.

Рассмотрим более сложную и интеллектуальную функцию, которая решает эти проблемы с помощью заранее подготовленных коллекций:


Функция ПреобразоватьСтрокуИнтеллектуально(Знач ИсходнаяСтрока) Экспорт
    
    // 1. Предварительно делим строку по заглавным буквам
    Шаблон = "([а-яё0-9])([А-ЯЁ])";
    СтрокаСПробелами = СтрЗаменитьПоРегулярномуВыражению(ИсходнаяСтрока, Шаблон, "$1 $2");
    
    МассивСлов = СтрРазделить(СтрокаСПробелами, " ", Ложь);
    
    // 2. Определяем списки исключений
    СловарьПредлогов = Новый Соответствие;
    СловарьПредлогов.Вставить("о", Истина);
    СловарьПредлогов.Вставить("об", Истина);
    СловарьПредлогов.Вставить("и", Истина);
    СловарьПредлогов.Вставить("в", Истина);
    СловарьПредлогов.Вставить("на", Истина);
    СловарьПредлогов.Вставить("без", Истина);
    СловарьПредлогов.Вставить("для", Истина);
    СловарьПредлогов.Вставить("по", Истина);
    СловарьПредлогов.Вставить("при", Истина);
    
    СловарьАббревиатур = Новый Соответствие;
    СловарьАббревиатур.Вставить("ндс", "НДС");
    СловарьАббревиатур.Вставить("ндфл", "НДФЛ");
    СловарьАббревиатур.Вставить("пфр", "ПФР");
    СловарьАббревиатур.Вставить("фсс", "ФСС");
    СловарьАббревиатур.Вставить("усно", "УСНО");
    
    // 3. Обрабатываем каждое слово индивидуально
    Для Индекс = 0 По МассивСлов.ВГраница() Цикл
        СловоНижнийРегистр = НРег(МассивСлов[Индекс]);
        
        Если Индекс = 0 Тогда
            // Первое слово предложения всегда пишем с заглавной буквы
            МассивСлов[Индекс] = ТРег(МассивСлов[Индекс]);
        ИначеЕсли СловарьАббревиатур.Получить(СловоНижнийРегистр) <> Неопределено Тогда
            // Если это аббревиатура - восстанавливаем её правильный верхний регистр
            МассивСлов[Индекс] = СловарьАббревиатур.Получить(СловоНижнийРегистр);
        ИначеЕсли СловарьПредлогов.Получить(СловоНижнийРегистр) <> Неопределено Тогда
            // Если это предлог или союз - пишем его строчными буквами
            МассивСлов[Индекс] = СловоНижнийРегистр;
        Иначе
            // Обычное значимое слово пишем со строчной буквы (в стиле обычного предложения)
            МассивСлов[Индекс] = СловоНижнийРегистр;
        КонецЕсли;
    КонецЦикла;
    
    Возврат СтрСоединить(МассивСлов, " ");
КонецФункции

Давайте разберем по шагам, какие преимущества дает этот алгоритм:

Резюме и рекомендации

Выбор конкретного метода зависит от версии используемой вами технологической платформы 1С и требований к производительности:

← На главную