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

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

При разработке механизмов обмена данными или обработке текстовых логов программисты 1С часто сталкиваются с необходимостью извлечь конкретные значения из строк со сложной структурой. В этой статье мы подробно разберем, как с помощью регулярных выражений получить идентификаторы, текстовые описания и опциональные коды из строки формата * SOL:1201 тут слова строки текста , EXPOZITIE SТ *.

Постановка задачи и анализ структуры данных

Представим, что нам нужно разобрать строку и поместить данные в следующие переменные:

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

Способ 1: Использование объекта VBScript.RegExp (традиционный метод)

Долгое время в 1С единственным способом работы с регулярными выражениями было использование COM-объекта. Этот метод до сих пор актуален для старых версий платформы и обычных форм. Рассмотрим код, который создает объект и настраивает его для поиска.


// Создаем объект регулярного выражения
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина; // Игнорировать регистр
RegExp.Global = Ложь;       // Нам нужно только первое совпадение
RegExp.MultiLine = Ложь;    // Обрабатываем одну строку

// Устанавливаем паттерн
RegExp.Pattern = "SOL:(\d{4})(?:-\s*(\d{4}))?\s+(.*?)\s*,\s*EXPOZITIE\s*([A-Z]{1,2})?";

Разберем, что означает этот паттерн по шагам:

  1. SOL:(\d{4}) — ищем подстроку "SOL:", после которой идут ровно 4 цифры. Скобки создают захватывающую группу, чтобы мы могли вытащить это число.
  2. (?:-\s*(\d{4}))? — эта часть отвечает за диапазон. (?:...) — незахватывающая группа для группировки символов тире и цифр. Знак ? в конце делает всю группу необязательной. Внутри нее (\d{4}) — это вторая захватывающая группа для второго числа.
  3. \s+(.*?)\s*, — ищем текст. .*? означает "любые символы в минимальном количестве" (ленивый поиск), пока не встретим запятую. Это позволяет нам корректно захватить "тут слова строки текста".
  4. EXPOZITIE\s*([A-Z]{1,2})? — ищем ключевое слово и опционально захватываем 1 или 2 буквы латиницы.

Извлечение результатов из SubMatches

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


ТекстИсточник = "* SOL:1201-1500 тут слова строки текста , EXPOZITIE ST *";
Matches = RegExp.Execute(ТекстИсточник);

Если Matches.Count > 0 Тогда
    Match = Matches.Item(0);
    
    // Индексация SubMatches начинается с 0
    SOL = Match.SubMatches(0); // "1201"
    SOL2 = Match.SubMatches(1); // "1500" или пустая строка
    СтрТХТ = СокрЛП(Match.SubMatches(2)); // "тут слова строки текста"
    EXPOZITIE = Match.SubMatches(3); // "ST"
    
    // Дополнительная проверка для SOL2
    Если ПустаяСтрока(SOL2) Тогда
        SOL2 = SOL;
    КонецЕсли;
КонецЕсли;

Способ 2: Нативные регулярные выражения в 1С 8.3.24+

Если вы работаете на современной платформе (начиная с версии 8.3.24), рекомендуется использовать встроенные классы РегулярноеВыражение. Это работает быстрее, стабильнее на Linux и не требует COM-соединения. Проанализируем, как изменится наш код.


// В нативном 1С синтаксис немного отличается
Паттерн = "SOL:(\d{4})(?:-\s*(\d{4}))?\s+(.*?)\s*,\s*EXPOZITIE\s*([A-Z]{1,2})?";
РегВыр = Новый РегулярноеВыражение(Паттерн);

Результат = РегВыр.Найти(ТекстИсточник);

Если Результат <> Неопределено Тогда
    // Группы доступны через метод Группы.Получить()
    SOL = Результат.Группы.Получить(1).Значение;
    // Обратите внимание, что в нативном 1С индекс 0 - это вся найденная строка,
    // а индексы 1, 2... - это захватывающие группы.
    
    SOL2 = ?(Результат.Группы.Количество() > 2, Результат.Группы.Получить(2).Значение, "");
    СтрТХТ = СокрЛП(Результат.Группы.Получить(3).Значение);
    
    Если Результат.Группы.Количество() > 4 Тогда
        EXPOZITIE = Результат.Группы.Получить(4).Значение;
    КонецЕсли;
КонецЕсли;

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

Как справедливо заметили некоторые участники обсуждения, в простых случаях можно обойтись без регулярных выражений, используя метод СтрРазделить(). Это может быть полезно, если структура строки гарантированно стабильна. Выясним причину, почему это иногда удобнее: такой код легче читать разработчикам, не знакомым с синтаксисом Regex.

  1. Разделим строку по запятой, чтобы отсечь блок EXPOZITIE.
  2. В первой части найдем вхождение "SOL:" и удалим всё, что идет до него.
  3. Используем СокрЛП() для очистки лишних пробелов.

ЧастиСтроки = СтрРазделить(ТекстИсточник, ",");
Если ЧастиСтроки.Количество() >= 2 Тогда
    // Обработка левой части (SOL и текст)
    ЛеваяЧасть = СтрЗаменить(ЧастиСтроки[0], "*", "");
    // Далее логика поиска двоеточия и пробелов...
    
    // Обработка правой части (EXPOZITIE)
    ПраваяЧасть = СтрЗаменить(ЧастиСтроки[1], "*", "");
    Если СтрНайти(ПраваяЧасть, "EXPOZITIE") > 0 Тогда
        EXPOZITIE = СокрЛП(СтрЗаменить(ПраваяЧасть, "EXPOZITIE", ""));
    КонецЕсли;
КонецЕсли;

Важные нюансы и советы

1. Работа с кириллицей. Если в паттерне вы используете \w, помните, что в реализации VBScript.RegExp этот класс символов может не включать русские буквы. Для надежности используйте . (любой символ) или явно указывайте диапазоны [а-яА-ЯёЁ].

2. Ленивые квантификаторы. Использование .*? вместо .* критически важно, когда в строке может быть несколько запятых. Ленивый квантификатор заставит регулярку остановиться на ближайшей запятой, а не поглощать текст до самого конца строки.

3. Проверка на пустые значения. Всегда проверяйте результат работы регулярного выражения. Если группа опциональна (как наш EXPOZITIE), метод SubMatches вернет пустую строку, а в нативном 1С группа может иметь пустое свойство Значение. Проанализируем это в коде, чтобы избежать ошибок рантайма.

Рассмотренные нами методы позволяют гибко настраивать парсинг строк под любые нужды. Регулярные выражения — это мощный инструмент, который при правильном подходе экономит десятки строк кода и делает обработку данных более надежной.

← На главную