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