При работе со строковыми данными в 1С часто возникает задача поиска и извлечения адресной информации, такой как e-mail. Простой поиск символа @ с помощью функции СтрНайти не всегда удобен, так как адрес может быть окружен знаками препинания или располагаться внутри сложного текста. Рассмотрим подробнее несколько способов решения этой задачи: использование встроенных средств платформы 1С, работу через COM-объект VBScript.RegExp и алгоритм строкового парсинга.
Начиная с версии платформы 8.3.23, в 1С добавлена встроенная кроссплатформенная поддержка регулярных выражений стандарта ICU. Это наиболее универсальный и безопасный способ, поскольку он работает на любых операционных системах (включая Linux), а также в веб-клиенте без вызова внешних библиотек.
Для поиска всех вхождений e-mail в тексте воспользуемся функцией СтрНайтиВсеПоРегулярномуВыражению. Проанализируем пример кода:
Шаблон = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}";
ТекстИсточника = "Свяжитесь с нами по адресу vasya@mail.ru или support@company.com для уточнения деталей.";
МассивРезультатов = СтрНайтиВсеПоРегулярномуВыражению(ТекстИсточника, Шаблон);
Для Каждого Результат Из МассивРезультатов Цикл
НайденныйEmail = Сред(ТекстИсточника, Результат.НачальнаяПозиция, Результат.Длина);
Сообщить("Найден адрес: " + НайденныйEmail);
КонецЦикла;
Если необходимо обработать кириллические доменные имена (например, адреса в зоне .рф), расширим диапазон символов в шаблоне:
Шаблон = "[a-zA-Zа-яА-Я0-9._%+-]+@[a-zA-Zа-яА-Я0-9.-]+\.[a-zA-Zа-яА-Я]{2,}";
В более ранних версиях платформы (до 8.3.23) штатного механизма регулярных выражений не было. В среде Windows для этого традиционно применяется объект VBScript.RegExp.
Важное ограничение: данный подход работает только под управлением ОС Windows. В тонком клиенте на Linux или в веб-клиенте вызов COMОбъект приведет к ошибке, поэтому обработку через COM необходимо выполнять на стороне сервера под Windows.
Разберем по шагам пример извлечения имени пользователя и домена с помощью скобочных групп (подмасок):
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина; // Игнорировать регистр
RegExp.Global = Истина; // Поиск всех вхождений шаблона
RegExp.MultiLine = Ложь; // Многострочный режим
RegExp.Pattern = "([+0-9A-Za-z._-]+)@([A-Za-z0-9.-]+\.[A-Za-z]{2,})";
СтрВход = "Контактный адрес: vasya@mail.ru";
МассивСовпадений = RegExp.Execute(СтрВход);
Если МассивСовпадений.Count() > 0 Тогда
// Получаем первое найденное совпадение
Совпадение = МассивСовпадений.Item(0);
// Извлекаем подстроки, захваченные скобками в регулярном выражении
Подмаски = Совпадение.SubMatches;
ДоСобаки = Подмаски.Item(0);
ПослеСобаки = Подмаски.Item(1);
ПолныйАдрес = Совпадение.Value;
Сообщить("Логин: " + ДоСобаки);
Сообщить("Домен: " + ПослеСобаки);
Сообщить("Полный e-mail: " + ПолныйАдрес);
КонецЕсли;
Обратите внимание на составление регулярного выражения: не рекомендуется использовать конструкции вида [A-z], так как в таблице ASCII между заглавными и строчными латинскими буквами расположены специальные символы (квадратные скобки, символ подчеркивания и др.), что может привести к некорректным срабатываниям. Безопаснее явно указывать [a-zA-Z] или задавать свойство RegExp.IgnoreCase = Истина.
Если решение должно работать на версиях платформы ниже 8.3.23 в Linux или веб-клиенте без вызова внешних библиотек, поиск можно реализовать встроенными функциями работы со строками.
Рассмотрим алгоритм действий:
СтрНайти находим позицию символа @ в тексте.@ влево, пока не встретим недопустимый символ (пробел, кавычка, запятая, символ переноса строки) — это сформирует имя ящика.@ вправо до первого недопустимого разделителя — это сформирует доменную часть.В рамках темы также обсуждался вопрос массовой замены конструкций вызова справочников в коде модулей (например, замена Справочники.КлассификаторЕдиницИзмерения.НайтиПоКоду("168") на _ПовтИсп.ПолучитьЭлементПоКоду("КлассификаторЕдиницИзмерения", "168")).
В версии 8.3.23 и выше данная задача рефлексии и рефакторинга решается функцией СтрЗаменитьПоРегулярномуВыражению с использованием ссылок на захваченные группы ($1 и $2):
ИсходныйТекст = "Объект = Справочники.КлассификаторЕдиницИзмерения.НайтиПоКоду(""168"");";
ШаблонЗамены = "Справочники\.([A-Za-z0-9_]+)\.НайтиПоКоду\(([^)]+)\)";
СтрокаЗамены = "_ПовтИсп.ПолучитьЭлементПоКоду(""$1"", $2)";
Результат = СтрЗаменитьПоРегулярномуВыражению(ИсходныйТекст, ШаблонЗамены, СтрокаЗамены);
Для более ранних версий платформы аналогичный рефакторинг модулей выполняется штатными инструментами Конфигуратора через диалог «Глобальный поиск и замена».