К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как проверить строку на вхождение подстроки в 1С

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

Задача проверить, содержит ли строка нужную подстроку, встречается в 1С постоянно: при разборе наименований номенклатуры, проверке адресов, фильтрации файлов по имени, валидации введённых пользователем данных. Встроенный язык платформы даёт для этого несколько инструментов, и выбор конкретного зависит от версии платформы, требований к регистру символов и количества искомых значений.

Основной рабочий инструмент — функция СтрНайти(), появившаяся в платформе 8.3.6 и ставшая стандартом для новых разработок. В старом коде и в режиме совместимости встречается устаревшая Найти(), которая работает по тем же принципам. Обе возвращают позицию первого вхождения подстроки, а если вхождения нет — число 0. Именно сравнение результата с нулём и есть «проверка на вхождение».

Ниже разобраны синтаксис и примеры кода, нюансы регистра и направления поиска, проверка нескольких подстрок, типовые ошибки и способы убедиться, что проверка работает корректно на реальных данных.

Базовая проверка через СтрНайти

Функция СтрНайти() принимает минимум два параметра: строку, в которой ищем, и подстроку, которую ищем. Возвращаемое значение — позиция первого символа найденного вхождения (нумерация с единицы) или 0, если совпадений нет. Поэтому проверка на вхождение сводится к простому условию.

Строка = "Контрагент ООО Ромашка, договор № 45";

Если СтрНайти(Строка, "Ромашка") > 0 Тогда

Сообщить("Подстрока найдена");

Иначе

Сообщить("Вхождения нет");

КонецЕсли;

Такой приём подходит для большинства прикладных задач: фильтрации списков, проверки комментариев, поиска ключевых слов в наименованиях.

Если подстрока пустая, функция вернёт 1 — формально пустая строка «входит» в любую строку. Это частый источник логических ошибок, когда искомое значение берётся из реквизита, который пользователь не заполнил. Перед поиском стоит проверять подстроку на пустоту через ПустаяСтрока() или ЗначениеЗаполнено().

bsl
Если СтрНайти(НРег(Наименование), НРег(Искомое)) > 0 Тогда
	// вхождение найдено без учёта регистра
КонецЕсли;

Устаревшая функция Найти и совместимость

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

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

Поиск без учёта регистра

И СтрНайти(), и Найти() чувствительны к регистру: строка «склад» не будет найдена в тексте «Основной Склад». Для пользовательских данных это почти всегда нежелательно — сотрудники вводят наименования и комментарии в произвольном регистре.

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

Наименование = "Кабель ВВГнг-LS 3х2.5";

Искомое = "ввгнг";

Если СтрНайти(НРег(Наименование), НРег(Искомое)) > 0 Тогда

// совпадение найдено независимо от регистра

КонецЕсли;

Отдельная ловушка — буква «ё». Функции регистра не заменяют «ё» на «е», поэтому «елка» и «ёлка» — разные строки. Если пользователи вводят данные непоследовательно, имеет смысл дополнительно выполнять замену СтрЗаменить(Строка, "ё", "е") перед сравнением.

Направление поиска и позиция начала

У СтрНайти() есть необязательные параметры: направление поиска, начальная позиция и номер вхождения. Они полезны, когда нужно найти не первое вхождение, а, например, последнее или второе по счёту.

// Поиск последнего вхождения

Позиция = СтрНайти(ИмяФайла, ".", НаправлениеПоиска.СКонца);

// Поиск второго вхождения

Позиция = СтрНайти(Текст, ";", , 2);

Типичный прикладной сценарий — извлечь расширение файла: поиск точки с конца строки надёжнее, чем с начала, потому что точка может встречаться и в имени файла. Аналогично поиск с конца используют при разборе путей, чтобы отделить имя файла от каталога по последнему разделителю.

Если подстрока должна находиться строго в начале строки, сравнивайте результат с единицей: СтрНайти(Строка, Префикс) = 1. Для проверки окончания строки удобнее функции СтрНачинаетсяС() и СтрЗаканчиваетсяНа(), доступные в свежих версиях платформы, — они сразу возвращают булево и делают код читабельнее.

Проверка вхождения нескольких подстрок

Когда нужно проверить наличие любого из нескольких значений (например, список стоп-слов или допустимых типов документов), удобно пройти по массиву или списку значений в цикле и прерваться при первом совпадении.

СтопСлова = Новый Массив;

СтопСлова.Добавить("брак");

СтопСлова.Добавить("возврат");

Найдено = Ложь;

Для Каждого Слово Из СтопСлова Цикл

Если СтрНайти(НРег(Комментарий), Слово) > 0 Тогда

Найдено = Истина;

Прервать;

КонецЕсли;

КонецЦикла;

Если требуется, чтобы присутствовали все подстроки одновременно, логика зеркальная: при первом отсутствии вхождения устанавливайте флаг в Ложь и прерывайте цикл. Для сложных шаблонов — например, «цифры, затем буква, затем дефис» — простого поиска недостаточно; в таких случаях либо комбинируют несколько проверок, либо используют объекты работы с регулярными выражениями через внешние компоненты, что выходит за рамки типовых задач.

Маршрут решения

Как выбрать действие

Нужно просто узнать, есть ли подстрокаСтрНайти(Строка, Подстрока) > 0
Регистр символов не важенСтрНайти(НРег(Строка), НРег(Подстрока)) > 0
Подстрока должна быть в начале строкиСтрНачинаетсяС(Строка, Подстрока) или СтрНайти(..) = 1
Нужно последнее вхождение (например, расширение файла)СтрНайти с НаправлениеПоиска.СКонца
Платформа старше 8.3.6 или режим совместимостиИспользуйте Найти() вместо СтрНайти()

Проверка в запросах: ПОДОБНО

При отборе данных в запросах строковые функции встроенного языка недоступны — там используется оператор ПОДОБНО с шаблоном. Символ % означает любую последовательность символов, поэтому проверка вхождения выглядит так:

ГДЕ

Номенклатура.Наименование ПОДОБНО "%кабель%"

В динамических списках и СКД параметр удобно формировать конкатенацией: "%" + СтрокаПоиска + "%". Учтите, что символы %, _, [ внутри самой искомой строки воспринимаются как служебные и требуют экранирования через параметр СПЕЦСИМВОЛ, иначе результат отбора будет неверным.

Поиск по ПОДОБНО с ведущим процентом не использует индексы и на больших таблицах может работать медленно. Если такой отбор выполняется часто по справочнику с сотнями тысяч элементов, стоит продумать альтернативу — например, полнотекстовый поиск или отдельное поле для нормализованного значения.

Типичные ошибки и как их избежать

Большинство проблем с проверкой вхождения связано не с самой функцией, а с подготовкой данных. Пустая подстрока, лишние пробелы, разный регистр и буква «ё» дают ложные срабатывания или, наоборот, пропускают очевидные совпадения.

Перед поиском полезно обрезать пробелы через СокрЛП() — пользователи нередко копируют значения с пробелами по краям. А при сравнении данных из файлов учитывайте неразрывные пробелы и табуляции, которые визуально неотличимы от обычных пробелов.

Типичные ошибки
01
Поиск пустой подстроки: СтрНайти вернёт 1, и проверка ложно сработает — проверяйте значение на пустоту до поиска
02
Игнорирование регистра: «Склад» не найдётся в «склад» — приводите обе строки к одному регистру
03
Забытая буква «ё»: «ёлка» и «елка» считаются разными строками — нормализуйте текст при необходимости
04
Использование СтрНайти в режиме совместимости ниже 8.3.6 — модуль не скомпилируется, применяйте Найти()
05
ПОДОБНО без экранирования % и _ в пользовательском вводе — отбор возвращает лишние строки

Как проверить корректность результата

После внедрения проверки протестируйте её на граничных случаях, а не только на «удобном» примере. Набор контрольных данных для отладки обычно включает пустую строку, строку без вхождения, вхождение в начале, в середине и в конце, а также значения в другом регистре.

Контрольные точки

Как проверить результат

Подстрока в середине строки
Норма

СтрНайти возвращает позицию больше 1

Тревожный признак

Возвращает 0 при явно видимом совпадении — проверьте регистр и скрытые символы

Пустая подстрока
Норма

Проверка отклонена до вызова поиска

Тревожный признак

Функция вернула 1 и логика сработала ложно

Разный регистр данных
Норма

Совпадение находится после НРег/ВРег

Тревожный признак

Вхождение не находится — регистр не нормализован

Вхождение в конце строки
Норма

Позиция + длина подстроки - 1 = длина строки

Тревожный признак

Поиск обрезает хвост при дальнейшей обработке

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

Итог

Что важно запомнить

Проверка вхождения — это СтрНайти(Строка, Подстрока) > 0 (или Найти на старых платформах). Для пользовательских данных нормализуйте регистр и букву «ё», проверяйте подстроку на пустоту, а в запросах используйте ПОДОБНО с экранированием служебных символов.

Частые вопросы

Чем СтрНайти отличается от Найти?

Функционально — почти ничем: обе возвращают позицию первого вхождения или 0. СтрНайти появилась в платформе 8.3.6 как часть обновлённого семейства строковых функций и поддерживает расширенные параметры (направление, номер вхождения). Найти оставлена для обратной совместимости и применяется в старых конфигурациях.

Как проверить, что строка содержит только цифры?

Поиска вхождения здесь недостаточно. Обычно проверяют каждый символ в цикле на принадлежность набору «0123456789» или пытаются преобразовать строку в число с обработкой исключения. Второй вариант проще, но допускает знак минуса и разделитель дробной части, что не всегда желательно.

Почему СтрНайти не находит подстроку, которая явно есть в строке?

Чаще всего причины три: разный регистр букв, буква «ё» вместо «е» и невидимые символы — неразрывные пробелы или табуляции, скопированные из документов. Выведите обе строки в сообщение с явными границами (например, в квадратных скобках) и сравните посимвольно.

Как найти все вхождения подстроки, а не только первое?

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

Можно ли искать по шаблону со звёздочкой, как в проводнике?

Во встроенном языке напрямую — нет. В запросах частично это закрывает ПОДОБНО с символами % и _. Для полноценных шаблонов в коде приходится реализовывать собственное сопоставление или подключать регулярные выражения через внешние средства.

Что быстрее: СтрНайти или ПОДОБНО в запросе?

Это разные сценарии. СтрНайти работает с уже загруженными в память строками и очень быстра. ПОДОБНО фильтрует данные на стороне СУБД и избавляет от выгрузки лишних записей, но с ведущим % не использует индекс. При отборе из большой таблицы выгоднее отфильтровать запросом, при обработке небольшого набора в памяти — СтрНайти.