В практике разработчика 1С часто возникает задача очистки строковых данных от вспомогательных символов. Типичный пример — работа со СНИЛС, ИНН или номерами телефонов. На вход системы поступает строка вида «171-076-387 62», а для алгоритмов проверки или выгрузки в государственные органы требуется получить «чистую» строку из цифр: «17107638762». Рассмотрим подробнее, как решить эту задачу различными способами, проанализируем их эффективность и выберем наиболее оптимальный вариант.
Самый простой и очевидный метод, который первым приходит в голову — это последовательное использование встроенной функции СтрЗаменить. Мы просто указываем, какой символ нужно найти и на что его заменить (в нашем случае — на пустую строку).
Разберем пример кода, предложенный на форуме:
ИсходнаяСтрока = "171-076-387 62";
Результат = СтрЗаменить(СтрЗаменить(ИсходнаяСтрока, "-", ""), " ", "");
Этот метод отлично работает, если вы заранее и точно знаете, какие именно разделители могут встретиться во входных данных. Однако проанализируем ситуацию глубже: если во входящей строке появится точка, точка с запятой или латинская буква, этот код их проигнорирует и оставит в итоговой строке. Для разовой задачи это приемлемо, но для промышленного кода такая «жесткая привязка» к конкретным символам считается плохим тоном.
Чтобы сделать алгоритм более надежным, мы можем реализовать посимвольный перебор строки. Вместо того чтобы перечислять, что мы хотим «удалить», мы определим, что мы хотим «оставить». Это гораздо безопаснее, так как любые непредвиденные символы (мусор) будут автоматически отсечены.
Рассмотрим вариант реализации с использованием функции Найти:
ИсходнаяСтрока = "171-076-387 62";
Результат = "";
ДопустимыеСимволы = "0123456789";
Для Индекс = 1 По СтрДлина(ИсходнаяСтрока) Цикл
ТекущийСимвол = Сред(ИсходнаяСтрока, Индекс, 1);
Если Найти(ДопустимыеСимволы, ТекущийСимвол) > 0 Тогда
Результат = Результат + ТекущийСимвол;
КонецЕсли;
КонецЦикла;
Преимущество данного подхода заключается в его предсказуемости. Проанализируем ситуацию: что бы ни ввел пользователь, на выходе мы гарантированно получим только цифры. Однако у этого метода есть и обратная сторона — производительность. При каждой конкатенации (склеивании) строк Результат = Результат + ТекущийСимвол платформа 1С создает в памяти новую копию строки. На коротких строках типа СНИЛС это незаметно, но при обработке огромных массивов данных это может замедлить работу системы.
Если нам нужна максимальная производительность при переборе, стоит использовать проверку кодов символов. Вместо функции Найти, мы будем сравнивать код текущего символа с диапазоном цифр в таблице символов (ASCII/Unicode). Цифры от 0 до 9 имеют коды с 48 по 57 включительно.
Разберем, как это реализовать эффективно:
ИсходнаяСтрока = "171-076-387 62";
Результат = "";
Для Индекс = 1 По СтрДлина(ИсходнаяСтрока) Цикл
Код = КодСимвола(ИсходнаяСтрока, Индекс);
// Проверяем, входит ли код в диапазон цифр 0..9
Если Код >= 48 И Код <= 57 Тогда
Результат = Результат + Символ(Код);
КонецЕсли;
КонецЦикла;
Этот метод работает быстрее, так как сравнение чисел — это базовая и очень быстрая операция для процессора, в отличие от поиска подстроки в строке.
Для наиболее сложных случаев, когда нужно профессионально очистить строку от любого «мусора», идеально подходит объект VBScript.RegExp. Регулярные выражения позволяют одной командой удалить всё, что не является цифрой. Это самый гибкий способ, доступный в среде Windows.
Посмотрим на пример реализации:
РегВыражение = Новый COMОбъект("VBScript.RegExp");
РегВыражение.Global = Истина;
РегВыражение.IgnoreCase = Истина;
РегВыражение.MultiLine = Ложь;
// Шаблон \D означает "любой символ, не являющийся цифрой"
РегВыражение.Pattern = "\D";
ИсходнаяСтрока = "171-076-387 62";
Результат = РегВыражение.Replace(ИсходнаяСтрока, "");
Здесь мы создаем COMОбъект, задаем шаблон поиска \D (все не-цифры) и заменяем их на пустую строку. Выясним причину, почему этот метод считается лучшим для сложных интеграций: он позволяет одной строкой кода обрабатывать любые спецсимволы, переносы строк и невидимые знаки форматирования, которые могли попасть в данные при копировании из веб-браузера или Excel.
Проанализируем критически важный момент, который часто упускают начинающие разработчики. В сообщении 3 на форуме упоминалось, что данные похожи на номер ПФР (СНИЛС). СНИЛС может начинаться с нуля (например, «071-076-387 62»).
Если после очистки строки вы примените функцию Число(), то ведущий нуль будет потерян:
Важное правило: Если вы обрабатываете идентификаторы (ИНН, СНИЛС, номера счетов), результат всегда должен оставаться в типе Строка. Не преобразовывайте очищенные данные в числовой тип, если планируете использовать их как коды или номера документов.
Если вы работаете в современной конфигурации (например, БП 3.0, ЗУП 3.1, ERP), то в составе Библиотеки Стандартных Подсистем (БСП) уже есть готовые инструменты. Прежде чем писать свой велосипед, проверьте наличие функции в общем модуле ОбщегоНазначения.
Обычно функция называется ТолькоЦифрыВСтроке. Пример её использования:
ОчищенныйНомер = ОбщегоНазначения.ТолькоЦифрыВСтроке("171-076-387 62");
Эта функция внутри себя уже содержит оптимизированный алгоритм, учитывающий особенности платформы, и её использование делает ваш код более лаконичным и понятным для других разработчиков.
Мы рассмотрели несколько подходов к преобразованию строки. Выбор метода зависит от ваших задач:
Помните о сохранении ведущих нулей и всегда проверяйте входные данные на наличие непредвиденных символов. Правильная обработка строк — залог отсутствия ошибок в регламентированной отчетности и интеграционных механизмах.