В практике разработчика 1С 7.7 часто возникает задача разбора текстовых строк, где данные не разделены по колонкам, а идут сплошным текстом. Типичный пример — строка, содержащая Фамилию, Имя, Отчество и адрес электронной почты, разделенные пробелами. Поскольку длина ФИО может варьироваться, а отчество и вовсе отсутствовать, использование простых функций Лев() или Прав() с фиксированным количеством символов не подходит. Разберем несколько способов решения этой задачи: от простых манипуляций со строками до использования регулярных выражений.
Рассмотрим самый простой и элегантный способ, предложенный участниками обсуждения. Его суть заключается в том, чтобы превратить обычную строку в список строк, где каждое слово будет находиться на новой строке. В 1С 7.7 это реализуется через замену пробелов на системную константу РазделительСтрок.
Проанализируем алгоритм:
СтрПолучитьСтроку(), чтобы забрать нужный фрагмент (в нашем случае — четвертый, если структура строго "Фамилия Имя Отчество Почта").
// Исходная строка
МояСтрока = "Иванов Иван Иванович ivan@mail.ru";
// Преобразуем пробелы в переносы строк
СтрокаСРазделителями = СтрЗаменить(МояСтрока, " ", РазделительСтрок);
// Извлекаем 4-й элемент (почту)
Почта = СтрПолучитьСтроку(СтрокаСРазделителями, 4);
Предупреждение("Найденная почта: " + Почта);
Важное замечание: Этот метод сработает идеально только в том случае, если между словами строго по одному пробелу. Если пользователь случайно нажал пробел дважды, метод "сдвинет" индексы. Чтобы этого избежать, перед обработкой рекомендуется "схлопнуть" лишние пробелы.
// Очистка от двойных пробелов
Пока Найти(МояСтрока, " ") > 0 Цикл
МояСтрока = СтрЗаменить(МояСтрока, " ", " ");
КонецЦикла;
Если структура ФИО нестабильна (например, нет отчества или фамилия двойная через пробел), полагаться на номер слова (4-е или 5-е) нельзя. В этом случае логичнее искать почту по её уникальному признаку — символу @. Разберем, как найти границы почтового адреса внутри текста.
Посмотрим на логику реализации:
Функция ВырватьПочту(ВхСтр)
ПозСобаки = Найти(ВхСтр, "@");
Если ПозСобаки = 0 Тогда Возврат ""; КонецЕсли;
// Ищем начало (пробел слева)
Для к = 1 По ПозСобаки Цикл
Символ = Сред(ВхСтр, ПозСобаки - к, 1);
Если (Символ = " ") Или (ПозСобаки - к = 0) Тогда
ПозНачала = ПозСобаки - к + 1;
Прервать;
КонецЕсли;
КонецЦикла;
// Ищем конец (пробел справа)
ОстатокСтроки = Сред(ВхСтр, ПозСобаки);
ПозПробелаСправа = Найти(ОстатокСтроки, " ");
Если ПозПробелаСправа = 0 Тогда
ПозКонца = СтрДлина(ВхСтр);
Иначе
ПозКонца = ПозСобаки + ПозПробелаСправа - 2;
КонецЕсли;
Возврат Сред(ВхСтр, ПозНачала, ПозКонца - ПозНачала + 1);
КонецФункции
Для наиболее сложных случаев, когда данные могут быть сильно перемешаны, лучше всего использовать объект VBScript.RegExp. Это мощный инструмент, который позволяет извлекать подстроки по шаблону. В 1С 7.7 он подключается как внешний COM-объект.
Выясним, как это работает на практике:
// Создаем объект регулярных выражений
RegExp = СоздатьОбъект("VBScript.RegExp");
RegExp.IgnoreCase = 1; // Игнорировать регистр
RegExp.Global = 1; // Искать все вхождения
RegExp.Pattern = "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}"; // Шаблон почты
Matches = RegExp.Execute(ИсходнаяСтрока);
Если Matches.Count > 0 Тогда
Результат = Matches.Item(0).Value;
Сообщить("Найдена почта через RegExp: " + Результат);
КонецЕсли;
Преимущество этого метода в том, что нам совершенно неважно, сколько пробелов в строке, есть ли там цифры или другие символы. Регулярное выражение само найдет фрагмент, соответствующий стандарту написания email-адреса.
Зачастую в подобных выгрузках почта всегда является последним элементом строки. В 1С 7.7 нет встроенной функции поиска справа налево, но мы можем реализовать её самостоятельно. Проанализируем ситуацию: если мы найдем последний пробел в строке, то всё, что находится справа от него, и будет искомой почтой.
Рассмотрим пример функции:
Стр = СокрЛП(ИсходнаяСтрока);
Длина = СтрДлина(Стр);
Для НомерСимвола = 0 По Длина - 1 Цикл
ТекСимвол = Сред(Стр, Длина - НомерСимвола, 1);
Если ТекСимвол = " " Тогда
Почта = Сред(Стр, Длина - НомерСимвола + 1);
Прервать;
КонецЕсли;
КонецЦикла;
Этот метод работает быстрее, чем создание COM-объектов, и надежнее, чем поиск по фиксированному индексу строки, так как количество слов в ФИО (два, три или четыре) перестает иметь значение.
При выборе метода всегда учитывайте "грязность" ваших данных. Мы рекомендуем комбинировать подходы:
СокрЛП() для удаления лишних пробелов по краям.@. Если после выполнения СтрПолучитьСтроку(Стр, 4) в полученном фрагменте нет "собаки", значит структура строки нарушена и нужно переходить к поиску через RegExp или поиск по символу-маркеру.