Как быстро удалить излишние пробелы и табуляции из текста кода в 1С

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

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

Способ 1: Использование встроенных функций СтрЗаменить и СтрНайти

Это самый простой и интуитивно понятный способ, который не требует использования сторонних библиотек. Основная идея заключается в циклической замене двух пробелов на один до тех пор, пока в строке не останется ни одного вхождения двойного пробела. Проанализируем реализацию этого алгоритма:


Данные = "Текст    с    лишними    пробелами";
Данные = СокрЛП(Данные); // Удаляем пробелы по краям
Пока СтрНайти(Данные, "  ") <> 0 Цикл
    Данные = СтрЗаменить(Данные, "  ", " ");
КонецЦикла;

Преимущества метода: простота реализации и отсутствие зависимости от внешних объектов. Недостатки: низкая производительность на больших объемах текста, так как функция СтрЗаменить создает новую копию строки в памяти при каждой итерации. Кроме того, этот метод не обрабатывает табуляции и неразрывные пробелы (символ с кодом 160) за один проход.

Способ 2: Оптимизированная очистка через СтрРазделить и СтрСоединить

С появлением в платформе 8.3 функций СтрРазделить и СтрСоединить, обработка строк стала работать значительно быстрее. Разберем, как применить эти функции для нашей задачи. Мы можем разделить строку по набору символов-разделителей, а затем собрать её обратно, игнорируя пустые элементы.


// Определяем строку разделителей (пробел, табуляция, неразрывный пробел)
Разделители = " " + Символы.Таб + Символы.НПП;
// Разделяем строку на массив, пропуская пустые части
МассивСлов = СтрРазделить(ИсходныйТекст, Разделители, Ложь);
// Соединяем слова обратно через один пробел
Результат = СтрСоединить(МассивСлов, " ");

Рассмотрим подробнее параметры функции СтрРазделить. Третий параметр Ложь указывает платформе, что пустые строки, образовавшиеся в местах скопления нескольких пробелов, не должны включаться в итоговый массив. Это "магическим" образом удаляет все лишние пробелы за одну операцию. Выясним причину эффективности: 1С выполняет разбор и сборку строки на уровне внутреннего движка C++, что гораздо быстрее циклов на встроенном языке.

Способ 3: Использование регулярных выражений (VBScript.RegExp)

Если задача требует более тонкой настройки (например, удаление пробелов везде, кроме строк внутри кавычек), на помощь приходят регулярные выражения. В среде Windows мы можем использовать COM-объект VBScript.RegExp. Посмотрим на пример кода:


РегВыражение = Новый COMОбъект("VBScript.RegExp");
РегВыражение.IgnoreCase = Истина;
РегВыражение.Global = Истина;
РегВыражение.MultiLine = Истина;

// Паттерн для поиска последовательностей любых пробельных символов (пробел, таб, перенос)
// Для 1С важно добавить символ \xA0 (неразрывный пробел)
РегВыражение.Pattern = "[\s\xA0]{2,}"; 

Текст = "МояПеременная    =    15;   // Комментарий";
Результат = РегВыражение.Replace(Текст, " ");

Проанализируем ситуацию с паттерном. Метасимвол \s обозначает любой пробельный символ, но в реализации VBScript он не всегда корректно определяет неразрывный пробел (код 160). Поэтому мы используем квадратные скобки [\s\xA0] для явного указания обоих типов. Квантификатор {2,} говорит о том, что нужно искать вхождения длиной от двух символов и более. Это позволяет заменить "кучу" пробелов на один единственный.

Однако автор темы столкнулся с проблемой использования сложных условий, таких как Lookbehind (просмотр назад, (?<=...)). Важно знать: VBScript.RegExp является устаревшим движком и не поддерживает многие современные функции регулярных выражений. Если вам нужна максимальная мощь, рекомендуется использовать System.Text.RegularExpressions.Regex через NetObjectToCOM или внешние компоненты.

Способ 4: Посимвольный перебор (для специфических условий)

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


Функция ОчиститьЛишниеПробелы(Знач Текст)
    Результат = "";
    ПредыдущийБылПробелом = Ложь;
    
    Для Поз = 1 По СтрДлина(Текст) Цикл
        КодСимвола = КодСимвола(Текст, Поз);
        ТекущийПробел = (КодСимвола = 32 ИЛИ КодСимвола = 9 ИЛИ КодСимвола = 160);
        
        Если ТекущийПробел Тогда
            Если НЕ ПредыдущийБылПробелом Тогда
                Результат = Результат + " ";
                ПредыдущийБылПробелом = Истина;
            КонецЕсли;
        Иначе
            Результат = Результат + Сред(Текст, Поз, 1);
            ПредыдущийБылПробелом = Ложь;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

Разберем по шагам работу этого кода. Мы заводим флаг ПредыдущийБылПробелом. Когда алгоритм встречает первый пробел в серии, он добавляет его в результат и взводит флаг. Все последующие пробелы в этой серии будут проигнорированы, пока не встретится значащий символ. Это гарантирует, что любая последовательность пробелов/табов сожмется в один пробел.

Способ 5: Внешнее форматирование (Sublime Text, VS Code)

Если задача стоит разово или в рамках подготовки кода к "продакшену", рассмотрим вариант использования профессиональных текстовых редакторов. Пошагово это выглядит так:

  1. Копируем весь текст модуля.
  2. Вставляем в редактор (например, Sublime Text или VS Code).
  3. Используем встроенные функции Reindent (автоотступы) или плагины для языка 1С (BSL).
  4. Выполняем замену по регулярному выражению [ \t]+ на (один пробел).

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

Сводная таблица эффективности методов

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

  1. СтрРазделить/СтрСоединить — лучший выбор по соотношению "скорость/сложность" для типовых задач 1С.
  2. RegExp — необходим, когда нужно искать сложные паттерны (например, пробелы перед скобками, но не внутри кавычек).
  3. Цикл СтрЗаменить — допустим только для коротких строк в пользовательском интерфейсе.
  4. Внешние редакторы — идеальны для ручной чистки кода перед коммитом в репозиторий.

При обработке 25 000 модулей (как упоминалось в теме), наиболее надежным будет выгрузка конфигурации в файлы и использование скриптов на Python или C#, так как встроенный язык 1С при работе с огромными текстовыми массивами может значительно нагружать оперативную память из-за особенностей работы со строками типа Immutable.

← На главную