Разработка и Конфигурация · 11 мин
Как найти подстроку в строке в 1С
Как найти подстроку в строке в 1С: функции СтрНайти, Найти и СтрНайтиИПодсветить, учёт регистра, поиск с конца, примеры кода и типичные ошибки при работе со строками.
Поиск подстроки — одна из самых частых задач при разработке на встроенном языке 1С: разбор наименований, проверка введённых пользователем данных, анализ текста ошибок, фильтрация файлов по расширению. В зависимости от версии платформы и задачи используются разные функции: устаревшая Найти(), современная СтрНайти() или регулярные выражения через внешние компоненты.
Ключевой момент, который нужно понять сразу: функции поиска подстроки возвращают не булево «найдено/не найдено», а номер позиции первого символа найденной подстроки. Если подстрока не найдена, возвращается 0. Нумерация символов в строке начинается с 1, а не с 0 — это частая причина ошибок у разработчиков, пришедших из других языков.
Ниже разобраны синтаксис основных функций, учёт регистра, поиск нескольких вхождений, проверка результата и типичные ошибки, которые приводят к неверной логике обработки данных.
Базовый поиск подстроки функцией СтрНайти
Функция СтрНайти() появилась в платформе 8.3.6 и стала стандартным способом поиска подстроки. Её полный синтаксис:
СтрНайти(Строка, ПодстрокаПоиска, НаправлениеПоиска, НачальнаяПозиция, НомерВхождения)
Обязательны только первые два параметра: исходная строка и искомая подстрока. Остальные параметры управляют направлением поиска, стартовой позицией и номером вхождения. Простейший пример:
Наименование = "Бумага А4 офисная 80 г/м2";
Если СтрНайти(Наименование, "А4") > 0 Тогда
Сообщить("Это бумага формата А4");
КонецЕсли;
Функция возвращает позицию первого символа найденной подстроки. Для строки «Бумага А4 офисная» вызов СтрНайти(Наименование, "А4") вернёт 8, потому что «А» — восьмой символ строки. Если подстроки в строке нет, результат равен 0.
Функция Найти в старом коде
В конфигурациях, написанных до платформы 8.3.6, вместо СтрНайти() используется глобальная функция Найти() с более простым синтаксисом:
Позиция = Найти(Строка, Подстрока);
Она принимает только два параметра и всегда ищет с начала строки первое вхождение. Результат тот же: позиция первого символа или 0. Функция до сих пор работает, поэтому старый код не требует обязательной переделки, но в новых разработках рекомендуется СтрНайти() — она функциональнее и соответствует современным стандартам разработки.
Важный нюанс: у Найти() нет параметров направления и номера вхождения. Если в старом коде нужно было найти второе и последующие вхождения, разработчики вручную обрезали строку через Сред() и складывали позиции. При рефакторинге такие конструкции стоит заменять на СтрНайти() с параметром НомерВхождения — это убирает целый класс ошибок со смещением позиций.
СтрНайти или Найти
Современный стандарт с платформы 8.3.6. Поддерживает направление поиска, начальную позицию и номер вхождения. Использовать во всём новом коде.
Устаревшая функция, только поиск первого вхождения с начала строки. Оставлять в старом коде, менять при доработках.
Через VBScript.RegExp на Windows или внешние компоненты. Нужны только для сложных шаблонов, для простой подстроки избыточны.
Поиск с учётом и без учёта регистра
Встроенные функции поиска в 1С чувствительны к регистру: СтрНайти("Бумага А4", "а4") вернёт 0, потому что «а4» и «А4» — разные последовательности символов. Это одна из самых частых причин «неработающего» поиска.
Стандартный приём для поиска без учёта регистра — привести обе строки к одному регистру функциями ВРег() (верхний регистр) или НРег() (нижний регистр):
Если СтрНайти(НРег(Наименование), НРег(ПользовательскийВвод)) > 0 Тогда
// совпадение найдено независимо от регистра
КонецЕсли;
Учтите ограничение: НРег() и ВРег() корректно обрабатывают буквы, но не меняют цифры и спецсимволы — для задачи поиска это обычно не важно. А вот похожие по начертанию символы разных алфавитов (кириллическая «а» и латинская «a») регистром не свести: такие символы придётся нормализовать заменой через СтрЗаменить(), если данные приходят из внешних источников.
Поиск с конца строки и несколько вхождений
Третий параметр СтрНайти() — направление поиска из системного перечисления НаправлениеПоиска: СНачала (по умолчанию) или СКонца. Поиск с конца удобен, когда нужно последнее вхождение, например позиция последней точки в имени файла для выделения расширения:
ИмяФайла = "отчет.продажи.xlsx";
ПозицияТочки = СтрНайти(ИмяФайла, ".", НаправлениеПоиска.СКонца);
Если ПозицияТочки > 0 Тогда
Расширение = Сред(ИмяФайла, ПозицияТочки + 1); // "xlsx"
КонецЕсли;
Четвёртый параметр — начальная позиция, с которой начинается поиск. Пятый — номер вхождения: 1 — первое, 2 — второе и так далее. Так можно найти второе вхождение без ручной обрезки строки:
Строка = "Иванов;Петров;Сидоров";
ВтораяТочкаСЗапятой = СтрНайти(Строка, ";", , , 2); // позиция второго ";"
Если вхождений меньше, чем запрошенный номер, функция вернёт 0. Это удобно использовать в цикле для перебора всех вхождений: увеличивайте номер вхождения, пока результат не станет равен нулю.
НомерВхождения = 1;
Пока Истина Цикл
Позиция = СтрНайти(Текст, ";", , , НомерВхождения);
Если Позиция = 0 Тогда
Прервать;
КонецЕсли;
Сообщить("Вхождение " + НомерВхождения + " на позиции " + Позиция);
НомерВхождения = НомерВхождения + 1;
КонецЦикла;Проверка результата и обработка ошибок
Корректная проверка результата поиска — сравнение с нулём: Если Позиция > 0 Тогда или Если Позиция <> 0 Тогда. Не используйте конструкцию Если СтрНайти(...) Тогда без сравнения: в языке 1С число не преобразуется в булево автоматически, и такой код вызовет ошибку исполнения.
Отдельно проверяйте граничные случаи. Если исходная строка пустая, поиск всегда вернёт 0. Если искомая подстрока пустая, поведение зависит от платформы и может вернуть начальную позицию — не полагайтесь на это, а проверяйте входные данные явно через ПустаяСтрока() до поиска.
При работе с данными, введёнными пользователем или загруженными из файлов, полезно предварительно обрезать пробелы функцией СокрЛП(): лишний пробел в начале или конце искомой строки — типичная причина того, что заведомо существующая подстрока «не находится».
Как проверить результат
Число от 1 до длины строки — подстрока найдена
0 — подстрока не найдена или входные данные пустые
Позиция совпадает с ожидаемой при ручной проверке
Возвращается 0 — проверьте регистр, пробелы и похожие символы разных алфавитов
Совпадает с искомой подстрокой
Смещение на символ — проверьте, что нумерация велась с 1
Типичные ошибки при поиске подстроки
Первая группа ошибок связана с нумерацией позиций. Разработчики с опытом в других языках ожидают, что первый символ имеет индекс 0, и получают смещение на единицу при выделении подстроки через Сред(). В 1С первый символ строки — позиция 1, и результат СтрНайти() можно напрямую передавать в Сред() без корректировок.
Вторая группа — игнорирование регистра и пробелов. Поиск «не работает», хотя подстрока визуально присутствует: виноваты разный регистр букв, неразрывные пробелы из скопированного текста или кириллические буквы вместо латинских. Диагностируется это выводом кодов символов через КодСимвола() в подозрительной позиции.
Третья группа — использование поиска подстроки там, где нужны более строгие проверки. Например, проверка валюты документа по вхождению «USD» в строку найдёт и «USDT», и «NOTUSD». Для точных сравнений используйте равенство строк, для шаблонов — оператор ПОДОБНО в запросах, а не СтрНайти().
Поиск подстроки в запросах: оператор ПОДОБНО
Когда нужно отобрать записи в базе по вхождению подстроки — например, все товары, в наименовании которых есть слово «кабель», — используйте не перебор с СтрНайти(), а запрос с оператором ПОДОБНО. Это на порядки быстрее, потому что фильтрация выполняется на стороне СУБД:
Запрос.Текст =
"ВЫБРАТЬ Номенклатура.Ссылка
|ИЗ Справочник.Номенклатура КАК Номенклатура
|ГДЕ Номенклатура.Наименование ПОДОБНО &Шаблон";
Запрос.УстановитьПараметр("Шаблон", "%кабель%");
Символ % означает любую последовательность символов любой длины, _ — ровно один произвольный символ. Шаблон "%кабель%" находит вхождение в любом месте строки, "кабель%" — только в начале. Учтите, что специальные символы шаблона в искомом тексте нужно экранировать, иначе поиск даст неверный результат.
Производительный нюанс: шаблон, начинающийся с %, не позволяет СУБД использовать индекс по полю, поэтому на больших таблицах такой отбор выполняется полным сканированием. Для редких операций это приемлемо, но в массовых обработках и отчётах по крупным справочникам закладывайте время выполнения и по возможности сужайте выборку другими условиями.
Как выбрать способ поиска
Частые вопросы
Что возвращает СтрНайти, если подстрока не найдена?
Функция возвращает число 0. Поэтому проверка результата всегда строится как сравнение с нулём: Если СтрНайти(Строка, Подстрока) > 0 Тогда ... КонецЕсли. Отрицательных значений функция не возвращает.
Как проверить, что строка начинается с определённой подстроки?
Используйте функцию СтрНачинаетсяС(Строка, Подстрока) — она возвращает булево Истина или Ложь и читается нагляднее, чем сравнение позиции с единицей. Для конца строки есть парная функция СтрЗаканчиваетсяНа.
Почему СтрНайти не находит текст, который точно есть в строке?
Чаще всего причины три: разный регистр букв (поиск регистрозависим), лишние или неразрывные пробелы, визуально похожие символы разных алфавитов — кириллическая «а» вместо латинской. Приведите строки к одному регистру, обрежьте пробелы через СокрЛП и при необходимости проверьте коды символов функцией КодСимвола.
Как найти все вхождения подстроки, а не только первое?
Передайте в СтрНайти пятый параметр — номер вхождения — и перебирайте его в цикле от 1, пока функция не вернёт 0. Альтернатива для разбора строки по разделителю — функция СтрРазделить, которая сразу возвращает массив частей.
Чем заменить СтрНайти для поиска по шаблону с вариациями?
Для отбора данных в базе — оператор ПОДОБНО в запросе с символами % и _. Для сложных шаблонов в коде — регулярные выражения через объект VBScript.RegExp (только Windows) или внешние компоненты. Для простой фиксированной подстроки регулярные выражения избыточны.
Что важно запомнить
СтрНайти(Строка, Подстрока) возвращает позицию первого вхождения с нумерацией от 1 или 0, если подстрока не найдена. Поиск регистрозависим — при необходимости приводите строки к одному регистру. Для отбора данных в базе используйте ПОДОБНО в запросе, а результат поиска всегда проверяйте сравнением с нулём.