При решении задач нормализации справочников, построения нестандартных отчетов или интеграций разработчики нередко сталкиваются с необходимостью сложного парсинга строк: например, удалить из наименования номенклатуры габариты, артикулы или единицы измерения. Естественным желанием является выполнение такой операции прямо в секции ВЫБРАТЬ языка запросов. Разберем, возможно ли это сделать в рамках запроса 1С и какие существуют эффективные альтернативные подходы.
Выясним причину этого ограничения. Язык запросов платформы 1С:Предприятие представляет собой унифицированную декларативную абстракцию. При исполнении запроса сервер 1С транслирует его в диалект конкретной СУБД, на которой развернута информационная база: Microsoft SQL Server, PostgreSQL, Oracle Database, IBM DB2 или во внутренний формат файловой базы.
В стандартах SQL и в конкретных движках СУБД исторически нет единого механизма выполнения регулярных выражений на лету:
regexp_replace или REGEXP_REPLACE).Оператор ПОДОБНО (транслируемый в SQL-конструкцию LIKE) предназначен исключительно для сопоставления с простым шаблоном и возвращает логический результат (Истина или Ложь). Из-за кроссплатформенных различий между СУБД строковые функции в разделе ВЫБРАТЬ жестко ограничены: платформа поддерживает только ПОДСТРОКА, СОЕДИНИТЬСТРОКИ, ДЛИНА и ВЫРАЗИТЬ(... КАК СТРОКА(...)).
Следовательно, обработать строку по сложному шаблону регулярного выражения внутри тела запроса нельзя. Рассмотрим практические варианты решения этой задачи.
Начиная с версии платформы 8.3.23, в глобальном контексте встроенного языка 1С появилась полноценная кроссплатформенная поддержка регулярных выражений на базе библиотеки ICU. Если выборку запроса требуется обработать программно, мы выполняем обычный запрос, а затем трансформируем строки с помощью метода СтрЗаменитьПоРегулярномуВыражению.
Посмотрим на пример серверной постобработки данных:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.Наименование КАК ИсходноеНаименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| НЕ Номенклатура.ЭтоГруппа";
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
// Регулярное выражение для поиска размеров вида "0,5x3,53 м", "1.5х2 мм" и т.п.
ШаблонРазмера = "\s*\d+([.,]\d+)?\s*[xхXХ]\s*\d+([.,]\d+)?\s*(мм|см|м)?";
Пока Выборка.Следующий() Цикл
ОчищенноеНаименование = СтрЗаменитьПоРегулярномуВыражению(
Выборка.ИсходноеНаименование,
ШаблонРазмера,
""
);
// Дополнительно удаляем лишние двойные пробелы и концевые символы
ОчищенноеНаименование = СокрЛП(СтрЗаменитьПоРегулярномуВыражению(ОчищенноеНаименование, "\s+", " "));
КонецЦикла;
Если задача заключается в формировании отчета, в котором нужно вывести очищенные наименования, нет необходимости вручную перебирать результат запроса в коде. В СКД можно использовать вычисляемые поля с вызовом экспортных функций модулей.
Разберем по шагам, как это реализовать:
Функция ОчиститьНаименованиеОтРазмеров(Знач ИсходнаяСтрока) Экспорт
Если ПустаяСтрока(ИсходнаяСтрока) Тогда
Возврат "";
КонецЕсли;
Шаблон = "\s*\d+([.,]\d+)?\s*[xхXХ]\s*\d+([.,]\d+)?\s*(мм|см|м)?";
Результат = СтрЗаменитьПоРегулярномуВыражению(ИсходнаяСтрока, Шаблон, "");
Возврат СокрЛП(СтрЗаменитьПоРегулярномуВыражению(Результат, "\s+", " "));
КонецФункции
НаименованиеБезРазмеров.ИмяОбщегоМодуля.ОчиститьНаименованиеОтРазмеров(Наименование).Проанализируем производительность: регулярные выражения являются ресурсоемкой операцией для процессора. Если справочник содержит 50 000 – 100 000 и более позиций, регулярный разбор строк "на лету" при каждом обращении к данным или формировании отчетов приведет к заметным задержкам.
В высоконагруженных системах правильным решением является предварительная нормализация:
Номенклатура реквизит НаименованиеБезРазмера (или создаем подчиненный регистр сведений).ПередЗаписью или через ПодпискаНаСобытие автоматически рассчитываем значение реквизита при любом изменении элемента.ФоновыеЗадания.Выполнить).После такой нормализации в любых запросах можно напрямую обращаться к готовому полю Номенклатура.НаименованиеБезРазмера, получая максимальную скорость выборки и возможность использовать стандартные индексы СУБД.
Если конфигурация работает на устаревших версиях платформы, где нативных функций регулярных выражений нет, используются следующие методы:
ПодключитьВнешнююКомпоненту. Это наиболее производительный и безопасный вариант для серверов под управлением Linux и Windows.Новый COMОбъект("VBScript.RegExp"). Следует помнить, что данный вариант работает исключительно в среде Windows и не поддерживается на серверах под Linux.