В процессе разработки на платформе 1С:Предприятие 8 программисты часто сталкиваются с необходимостью поиска определенных данных внутри текстовых строк. Одной из самых распространенных функций для этого является СтрНайти. Однако стандартное поведение этой функции может преподнести сюрприз: она ищет подстроку, а не целое слово. Это приводит к ситуациям, когда при поиске короткого кода (например, «130») система находит его внутри более длинного кода («1306»), что является логической ошибкой во многих бизнес-задачах.
В данной статье мы подробно разберем, почему так происходит, и рассмотрим несколько надежных способов реализации поиска «точного совпадения» в произвольном тексте.
Проанализируем механику работы встроенной функции. Согласно документации, СтрНайти возвращает позицию первого вхождения искомой строки в исходной. Для платформы строка «130» — это просто последовательность из трех символов. Если эта последовательность встречается в составе строки «1306», функция честно вернет единицу (позицию начала вхождения).
Рассмотрим пример, который иллюстрирует проблему:
ИсходнаяСтрока = "Артикул 1306 на складе";
ИскомоеЗначение = "130";
Позиция = СтрНайти(ИсходнаяСтрока, ИскомоеЗначение);
// Позиция будет равна 9, хотя мы искали именно "130", а не часть "1306"
Для решения этой проблемы нам нужно научить программу отличать «слово целиком» от «части слова». Сделаем это с помощью нескольких проверенных методик.
Если искомые значения в строке разделены пробелами, запятыми или другими знаками препинания, самым правильным подходом будет разбиение строки в массив. Рассмотрим этот алгоритм по шагам:
СтрРазделить.=.Пример реализации:
Текст = "прав 1306 бючсп";
МассивСлов = СтрРазделить(Текст, " ", Ложь); // Разбиваем по пробелу
НайденоТочно = Ложь;
Для Каждого Слово Из МассивСлов Цикл
Если Слово = "130" Тогда
НайденоТочно = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Этот способ является наиболее надежным, так как оператор сравнения = проверяет полное идентичное совпадение строк.
Бывают ситуации, когда разбивать строку в массив слишком затратно по ресурсам или неудобно. В этом случае программисты 1С часто используют элегантный «хак». Мы искусственно добавляем разделители (пробелы) в начало и конец как исходной строки, так и искомого значения. Разберем, как это работает.
Если мы будем искать " 130 " (с пробелами) в строке " 1306 ", поиск вернет 0, так как после «0» идет «6», а не пробел. А в строке " 130 " поиск завершится успехом.
ИсходнаяСтрока = "Код 1306 и код 130";
Искомое = "130";
// Добавляем пробелы для поиска точного вхождения
Если СтрНайти(" " + ИсходнаяСтрока + " ", " " + Искомое + " ") > 0 Тогда
Сообщить("Найдено точное совпадение!");
КонецЕсли;
Важный момент: этот метод работает корректно только если в тексте нет других разделителей (точек, запятых), кроме пробела. Если они есть, их нужно предварительно заменить на пробелы функцией СтрЗаменить.
Для максимально точного поиска, учитывающего границы слов (пробелы, начало строки, знаки препинания), лучше всего подходят регулярные выражения. В языке 1С нет встроенного объекта RegExp, но мы можем воспользоваться COM-объектом VBScript.RegExp.
Проанализируем код:
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина; // Игнорировать регистр
RegExp.Global = Ложь; // Искать только первое вхождение
// Шаблон \b означает границу слова
RegExp.Pattern = "\b" + "130" + "\b";
ТекстДляПоиска = "склад 1306, ячейка 130";
Если RegExp.Test(ТекстДляПоиска) Тогда
Сообщить("Число 130 найдено как отдельное слово!");
КонецЕсли;
Символ \b в шаблоне гарантирует, что перед и после искомой подстроки нет других букв или цифр. Это самый «профессиональный» способ решения задачи.
Если задача стоит найти данные не в текстовой переменной, а в базе данных (например, найти все документы, где в комментарии указан код 130), то используется язык запросов. Здесь также возникает проблема частичного вхождения при использовании %.
Чтобы найти точное слово в запросе, нужно комбинировать условия:
ВЫБРАТЬ
Ссылка
ИЗ
Справочник.Номенклатура
ГДЕ
Наименование ПОДОБНО "130 %" // В начале строки
ИЛИ Наименование ПОДОБНО "% 130" // В конце строки
ИЛИ Наименование ПОДОБНО "% 130 %" // В середине строки
ИЛИ Наименование = "130" // Полное совпадение
При работе с большими объемами данных (например, поиск в цикле по тысячам строк) использование СтрНайти может замедлить работу системы. Рассмотрим рекомендации по оптимизации:
СтрРазделить в массив один раз, а затем загрузите этот массив в объект Соответствие или СписокЗначений.Соответствие работает значительно быстрее, чем многократный вызов СтрНайти или перебор массива.Функция СтрНайти — это мощный, но «простой» инструмент. Для поиска точных совпадений (целых слов) всегда используйте дополнительные проверки:
СтрРазделить.Выбор метода зависит от сложности структуры вашего текста и требований к производительности. Надеемся, эти шаги помогут вам избежать ошибок при обработке строковых данных в 1С!