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

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

В процессе разработки часто возникает задача автоматического форматирования текста. Типичный пример — разделение слов, которые «слиплись» из-за разного регистра, например, когда за строчной (маленькой) буквой сразу следует прописная (заглавная). Проанализируем различные подходы к решению этой задачи, начиная от простых алгоритмов перебора и заканчивая мощными инструментами регулярных выражений, появившимися в современных версиях платформы 1С:Предприятие 8.3.23.

Способ 1. Классический перебор строки в цикле

Разберем самый понятный и универсальный способ, который будет работать на любой версии платформы. Мы будем посимвольно обходить строку и проверять регистр текущего и следующего символа. Чтобы не зависеть от жестко прописанного алфавита, воспользуемся функциями НРег и ВРег.

Рассмотрим пример реализации функции, которая анализирует строку и собирает результат в новую переменную:


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

Важный нюанс: условие ТекСимвол <> ВРег(ТекСимвол) необходимо для того, чтобы исключить цифры и знаки препинания, которые при смене регистра не изменяются.

Способ 2. Использование вспомогательных масок ( placeholders )

Проанализируем более хитрый метод. Если мы хотим избежать сложной логики внутри цикла, можно предварительно подготовить строку. Сначала заменим все возможные маленькие буквы на один символ (например, «а»), а все большие — на другой (например, «А»). Тогда в модифицированной строке нам останется найти только сочетание «аА».

Посмотрим, как это выглядит в коде:


Функция ВставитьПробелЧерезМаску(Знач Стр)
    Маленькие = "аеёиоуыэюябвгджзйклмнпрстфхцчшщъь";
    Большие = ВРег(Маленькие);
    
    // Создаем "карту" строки, где все буквы приведены к двум видам
    МодифицированнаяСтрока = Стр;
    Для Индекс = 1 По СтрДлина(Маленькие) Цикл
        МодифицированнаяСтрока = СтрЗаменить(МодифицированнаяСтрока, Сред(Маленькие, Индекс, 1), "а");
        МодифицированнаяСтрока = СтрЗаменить(МодифицированнаяСтрока, Сред(Большие, Индекс, 1), "А");
    КонецЦикла;
    
    // Теперь ищем вхождение "аА" в маске и вставляем пробел в оригинал
    Позиция = СтрНайти(МодифицированнаяСтрока, "аА");
    Смещение = 0;
    Пока Позиция > 0 Цикл
        Стр = Сред(Стр, 1, Позиция + Смещение) + " " + Сред(Стр, Позиция + Смещение + 1);
        Смещение = Смещение + 1; // Учитываем добавленный пробел
        Позиция = СтрНайти(МодифицированнаяСтрока, "аА", , Позиция + 1);
    КонецЦикла;
    
    Возврат Стр;
КонецФункции

Способ 3. Регулярные выражения через COM (для версий ниже 8.3.23)

Если ваша платформа не самая свежая, но задача требует высокой скорости и краткости кода, можно использовать объект VBScript.RegExp. Выясним, как составить паттерн для поиска строчных и прописных букв.

Паттерн ([а-яё])([А-ЯЁ]) описывает две группы захвата: первая ищет маленькую букву, вторая — большую. Обратите внимание на букву «ё», она часто не входит в стандартный диапазон «а-я».


Функция ОбработатьРегуляркойCOM(ВхСтрока)
    RegExp = Новый COMОбъект("VBScript.RegExp");
    RegExp.Global = Истина;
    RegExp.Pattern = "([а-яё])([А-ЯЁ])";
    
    // В VBScript можно использовать $1 $2 для подстановки найденных групп
    Возврат RegExp.Replace(ВхСтрока, "$1 $2");
КонецФункции

Это решение изящное, но имеет ограничение: оно работает только в операционной системе Windows, так как использует COM-технологию.

Способ 4. Встроенные регулярные выражения в 1С 8.3.23

С выходом версии 8.3.23 в 1С появилась нативная поддержка регулярных выражений по стандарту ICU. Это наиболее производительный и современный метод. Рассмотрим, какие новые функции нам помогут:

  1. СтрНайтиПоРегулярномуВыражению() — поиск первого вхождения.
  2. СтрЗаменитьПоРегулярномуВыражению() — замена по шаблону.
  3. \p{Ll} — специальный литерал Unicode для любой строчной буквы.
  4. \p{Lu} — специальный литерал Unicode для любой прописной буквы.

Проанализируем ситуацию: в текущей реализации 1С 8.3.23 в методе замены пока отсутствует поддержка групп захвата (обращение через $1, $2). Поэтому для вставки пробела нам придется получить все вхождения и обработать их в цикле.


Функция ВставитьПробелы8323(Знач ВхСтрока)
    // Паттерн: строчная буква, за которой следует прописная
    Паттерн = "\p{Ll}\p{Lu}";
    
    // Получаем все найденные совпадения
    Результаты = СтрНайтиВсеПоРегулярномуВыражению(ВхСтрока, Паттерн);
    
    // Обрабатываем результаты с конца, чтобы не поплыли индексы
    Для Индекс = Результаты.Количество() - 1 По 0 Цикл
        ТекРезультат = Результаты[Индекс];
        // Вставляем пробел в середину найденной пары (длина пары всегда 2 символа)
        ВхСтрока = Сред(ВхСтрока, 1, ТекРезультат.НачальнаяПозиция) 
                 + " " 
                 + Сред(ВхСтрока, ТекРезультат.НачальнаяПозиция + 1);
    КонецЦикла;
    
    Возврат ВхСтрока;
КонецФункции

Технические нюансы и подводные камни

Разберем важный технический момент, связанный с «шестым битом», о котором часто говорят опытные программисты. В кодировке Unicode разница между кодом заглавной и строчной буквы кириллицы часто составляет 32 (это и есть 5-й или 6-й бит в зависимости от системы отсчета). Например, «А» (1040) и «а» (1072).

Внимание: полагаться на битовые операции опасно из-за буквы «Ё». У «Ё» код 1025, а у «ё» — 1105. Разница между ними — 80. Поэтому всегда используйте либо встроенные функции 1С (НРег/ВРег), либо Unicode-категории в регулярных выражениях (\p{L}).

Также помните, что новые функции платформы 8.3.23 по работе с регулярными выражениями доступны в основном на стороне сервера. Если вам нужна обработка на клиенте в тонком клиенте, убедитесь, что версия платформы поддерживает это, или используйте серверный вызов.

Подводя итог, для новых проектов на современных версиях 1С оптимальным будет использование \p{Ll}\p{Lu}, а для поддержки старых конфигураций — надежный метод со сравнением НРег() и ВРег().

← На главную