Как использовать регулярные выражения для обработки строк в запросах 1С?

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

При решении задач нормализации справочников, построения нестандартных отчетов или интеграций разработчики нередко сталкиваются с необходимостью сложного парсинга строк: например, удалить из наименования номенклатуры габариты, артикулы или единицы измерения. Естественным желанием является выполнение такой операции прямо в секции ВЫБРАТЬ языка запросов. Разберем, возможно ли это сделать в рамках запроса 1С и какие существуют эффективные альтернативные подходы.

Почему регулярные выражения недоступны в секции ВЫБРАТЬ

Выясним причину этого ограничения. Язык запросов платформы 1С:Предприятие представляет собой унифицированную декларативную абстракцию. При исполнении запроса сервер 1С транслирует его в диалект конкретной СУБД, на которой развернута информационная база: Microsoft SQL Server, PostgreSQL, Oracle Database, IBM DB2 или во внутренний формат файловой базы.

В стандартах SQL и в конкретных движках СУБД исторически нет единого механизма выполнения регулярных выражений на лету:

  1. В PostgreSQL и Oracle реализованы встроенные функции (такие как regexp_replace или REGEXP_REPLACE).
  2. В Microsoft SQL Server на уровне чистого T-SQL долгое время не было скалярных функций для регулярных выражений без подключения сборок CLR.
  3. В файловой СУБД 1С обработка данных опирается на собственный упрощенный движок.

Оператор ПОДОБНО (транслируемый в SQL-конструкцию LIKE) предназначен исключительно для сопоставления с простым шаблоном и возвращает логический результат (Истина или Ложь). Из-за кроссплатформенных различий между СУБД строковые функции в разделе ВЫБРАТЬ жестко ограничены: платформа поддерживает только ПОДСТРОКА, СОЕДИНИТЬСТРОКИ, ДЛИНА и ВЫРАЗИТЬ(... КАК СТРОКА(...)).

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

Вариант 1. Нативные методы регулярных выражений во встроенном языке (платформа 8.3.23 и выше)

Начиная с версии платформы 8.3.23, в глобальном контексте встроенного языка 1С появилась полноценная кроссплатформенная поддержка регулярных выражений на базе библиотеки ICU. Если выборку запроса требуется обработать программно, мы выполняем обычный запрос, а затем трансформируем строки с помощью метода СтрЗаменитьПоРегулярномуВыражению.

Посмотрим на пример серверной постобработки данных:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка,
    |	Номенклатура.Наименование КАК ИсходноеНаименование
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	НЕ Номенклатура.ЭтоГруппа";

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

// Регулярное выражение для поиска размеров вида "0,5x3,53 м", "1.5х2 мм" и т.п.
ШаблонРазмера = "\s*\d+([.,]\d+)?\s*[xхXХ]\s*\d+([.,]\d+)?\s*(мм|см|м)?";

Пока Выборка.Следующий() Цикл
    ОчищенноеНаименование = СтрЗаменитьПоРегулярномуВыражению(
        Выборка.ИсходноеНаименование, 
        ШаблонРазмера, 
        ""
    );
    // Дополнительно удаляем лишние двойные пробелы и концевые символы
    ОчищенноеНаименование = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(ОчищенноеНаименование, "\s+", " "));
КонецЦикла;

Вариант 2. Использование функций в Системе компоновки данных (СКД)

Если задача заключается в формировании отчета, в котором нужно вывести очищенные наименования, нет необходимости вручную перебирать результат запроса в коде. В СКД можно использовать вычисляемые поля с вызовом экспортных функций модулей.

Разберем по шагам, как это реализовать:

  1. Создаем в общем серверном модуле (с флагом Клиент (управляемое приложение) или Сервер в зависимости от режима компоновки) экспортную функцию очистки:

Функция ОчиститьНаименованиеОтРазмеров(Знач ИсходнаяСтрока) Экспорт
    Если ПустаяСтрока(ИсходнаяСтрока) Тогда
        Возврат "";
    КонецЕсли;
    
    Шаблон = "\s*\d+([.,]\d+)?\s*[xхXХ]\s*\d+([.,]\d+)?\s*(мм|см|м)?";
    Результат = СтрЗаменитьПоРегулярномуВыражению(ИсходнаяСтрока, Шаблон, "");
    Возврат СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Результат, "\s+", " "));
КонецФункции
  1. В схеме компоновки данных во вкладке Вычисляемые поля добавляем новое поле НаименованиеБезРазмеров.
  2. В колонке Выражение указываем вызов функции: ИмяОбщегоМодуля.ОчиститьНаименованиеОтРазмеров(Наименование).
  3. Используем полученное вычисляемое поле в настройках отчета (в группировках или колонках).

Вариант 3. Архитектурная нормализация данных (запись в отдельный реквизит)

Проанализируем производительность: регулярные выражения являются ресурсоемкой операцией для процессора. Если справочник содержит 50 000 – 100 000 и более позиций, регулярный разбор строк "на лету" при каждом обращении к данным или формировании отчетов приведет к заметным задержкам.

В высоконагруженных системах правильным решением является предварительная нормализация:

  1. Добавляем в справочник Номенклатура реквизит НаименованиеБезРазмера (или создаем подчиненный регистр сведений).
  2. В модуле объекта в обработчике события ПередЗаписью или через ПодпискаНаСобытие автоматически рассчитываем значение реквизита при любом изменении элемента.
  3. Для первоначального заполнения существующей базы выполняем разовую обработку с порционной записью (при необходимости задействуем механизм ФоновыеЗадания.Выполнить).

После такой нормализации в любых запросах можно напрямую обращаться к готовому полю Номенклатура.НаименованиеБезРазмера, получая максимальную скорость выборки и возможность использовать стандартные индексы СУБД.

Вариант 4. Работа на версиях платформы ниже 8.3.23

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

  1. Внешние компоненты Native API: кроссплатформенные библиотеки на C++ или Rust, загружаемые через ПодключитьВнешнююКомпоненту. Это наиболее производительный и безопасный вариант для серверов под управлением Linux и Windows.
  2. COM-объект VBScript.RegExp: классический способ через Новый COMОбъект("VBScript.RegExp"). Следует помнить, что данный вариант работает исключительно в среде Windows и не поддерживается на серверах под Linux.
← На главную