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

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

При работе со строковыми данными в 1С часто возникает задача извлечь подстроку, которая может соответствовать нескольким шаблонам одновременно. В таких случаях критически важно определить приоритет выбора: если в строке присутствует расширенный набор данных, мы хотим получить его, а если только базовый — ограничиться им. В этой статье мы подробно разберем, как реализовать логику выбора по приоритету с использованием объекта VBScript.RegExp.

Принцип упорядоченного чередования

Прежде всего, нам необходимо понять, как движок регулярных выражений (NFA), используемый в Windows и 1С, обрабатывает оператор «или» (символ |). В отличие от некоторых других логических систем, в регулярных выражениях этот оператор является зависимым от порядка. Движок проверяет альтернативы слева направо и останавливается на первой, которая подошла под условия поиска.

Рассмотрим ситуацию, когда нам нужно выбрать между длинной строкой «ABCDE_1234>» и короткой «ABCDE_». Если мы напишем шаблон как (ABCDE_|ABCDE_1234>), движок найдет короткое совпадение и сразу же вернет результат, даже не пытаясь проверить вторую часть. Поэтому главное правило приоритета гласит: всегда ставьте самое специфичное (длинное) условие первым, а более общее (короткое) — последним.

Разбор практической задачи

Допустим, у нас есть входящая строка вида "ABCDE_1234>". Нам нужно извлечь данные по следующей логике:

  1. Если в строке есть закрывающий символ >, мы забираем всю часть до него включительно.
  2. Если символа > нет, мы забираем только часть, заканчивающуюся на подчеркивание _.

Проанализируем базовое решение, предложенное в обсуждении:


// Пример шаблона с жестко заданным текстом
Шаблон = "(ABCDE_1234>|ABCDE_)";

Этот вариант работает для статического текста, но в реальной разработке 1С содержимое строки (например, артикул или идентификатор) заранее неизвестно. Нам нужно составить универсальный паттерн.

Создание универсального шаблона в 1С

Выясним причину, почему жесткое прописывание текста не подходит: данные могут меняться, и вместо «ABCDE» может прийти «1_Ф». Правильный подход заключается в использовании метасимволов и квантификаторов. Рассмотрим по шагам, как составить такой шаблон:

1. Сначала описываем приоритетный вариант (с символом >). Мы используем конструкцию, которая ищет любые символы до знака подчеркивания, затем цифры и завершающий символ. 2. Затем через | добавляем вариант поиска только до подчеркивания.

Пример реализации на встроенном языке 1С:


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

// Паттерн: (ЛюбыеСимволы_ЛюбыеСимволы>|ЛюбыеСимволы_)
// Используем [^>]* для предотвращения чрезмерного захвата
РегВыр.Pattern = "([^>]+_[^>]+>|[^>]+_)";

Текст = "ABCDE_1234>";
Результаты = РегВыр.Execute(Текст);

Если Результаты.Count > 0 Тогда
    НайденноеЗначение = Результаты.Item(0).Value;
    Сообщить("Результат: " + НайденноеЗначение);
КонецЕсли;

Использование жадности и необязательных групп

Посмотрим на ситуацию под другим углом. Вместо явного перечисления «или», мы можем использовать один паттерн с необязательной группой. Это более изящный способ решить задачу выбора по приоритету.

Разберем структуру паттерна ^.*?_([^>]*>)?:

Важный момент: в VBScript.RegExp жадные квантификаторы (такие как *) пытаются захватить как можно больше текста. Если в вашей строке может быть несколько символов >, обязательно используйте исключающий набор [^>]* вместо точки .*, чтобы захват остановился на первом встреченном маркере.

Обработка результатов и SubMatches

Проанализируем, как правильно извлекать данные, если мы используем скобки для группировки. В 1С объект Match содержит коллекцию SubMatches, которая позволяет обращаться к частям строки, попавшим в скобки.


Текст = "1_Ф>";
РегВыр.Pattern = "(.*_)(.*>)?";
Matches = РегВыр.Execute(Текст);

Если Matches.Count > 0 Тогда
    Match = Matches.Item(0);
    // Если вторая группа (.*>) найдена, склеиваем результат
    Если Match.SubMatches.Count > 1 И ЗначениеЗаполнено(Match.SubMatches.Item(1)) Тогда
        ИтоговыйРезультат = Match.SubMatches.Item(0) + Match.SubMatches.Item(1);
    Иначе
        ИтоговыйРезультат = Match.SubMatches.Item(0);
    КонецЕсли;
КонецЕсли;

Продвинутые техники: Утверждения (Lookarounds)

Хотя VBScript.RegExp не поддерживает поиск назад (lookbehind), он отлично справляется с положительным просмотром вперед. Это позволяет проверить наличие символа впереди, не включая его в само совпадение, если это требуется по бизнес-логике.

Например, паттерн .*_(?=.*>) найдет часть строки до подчеркивания только в том случае, если где-то дальше в строке встречается символ >. Это мощный инструмент для ветвления логики внутри одного регулярного выражения.

Резюме для реализации

Подводя итог, для реализации приоритетного выбора в 1С придерживайтесь следующих правил:

  1. Располагайте шаблоны от частного к общему. Сначала длинные и сложные, в конце — простые и короткие.
  2. Используйте ленивые квантификаторы *? или +?, если вам нужно найти ближайший разделитель, а не последний в строке.
  3. Тестируйте на граничных случаях. Проверяйте строки с несколькими разделителями (например, "ABC_DEF_123>"), чтобы убедиться, что логика захвата работает предсказуемо.
  4. Помните об ограничениях движка. В 1С используется классический NFA-движок через COM-объект, поэтому специфичные фичи современных языков (вроде именованных групп или условий) могут быть недоступны.

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

← На главную