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

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

1С: как найти символ или подстроку в строке

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

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

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

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

Базовый пример: найти символ в строке

Простейший вариант — поиск одного символа, например разделителя. Код ниже находит позицию запятой в строке с адресом:

Строка = "г. Москва, ул. Ленина, д. 5";

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

// Позиция = 11 — первая запятая стоит на 11-й позиции

Если символа в строке нет, функция вернёт 0. Это ключевой момент: результат поиска всегда нужно проверять перед тем, как использовать позицию в функциях Лев(), Прав() или Сред(). Иначе легко получить обрезанные или пустые данные, которые дальше попадут в документы и отчёты.

Поиск подстроки из нескольких символов выполняется аналогично:

Артикул = "ТОВ-00123-БР";

Если СтрНайти(Артикул, "-БР") > 0 Тогда

// артикул содержит признак брака

КонецЕсли;

Параметры функции СтрНайти подробно

Полный набор параметров позволяет решать нестандартные задачи без циклов и дополнительного кода. Разберём каждый из них.

ПараметрТипНазначение
СтрокаСтрокаИсходная строка, в которой выполняется поиск
ПодстрокаПоискаСтрокаИскомый символ или фрагмент
НаправлениеПоискаНаправлениеПоискаСНачала (по умолчанию) или СКонца
НачальнаяПозицияЧислоПозиция, с которой начинать поиск (по умолчанию 1)
НомерВхожденияЧислоКакое по счёту вхождение вернуть (по умолчанию 1)

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

Поиск с конца строки

Часто нужно найти последнее вхождение символа: например, точку перед расширением файла или последний разделитель в полном пути. Для этого используется параметр НаправлениеПоиска:

ИмяФайла = "Отчет.Продажи.Итоговый.xlsx";

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

Расширение = Сред(ИмяФайла, ПозицияТочки + 1); // "xlsx"

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

Тот же приём применяется для извлечения имени файла из полного пути — ищется последний обратный слэш, и всё, что после него, является именем файла.

bsl
Путь = "C:\Документы\Отчеты\Продажи.xlsx";
Поз = СтрНайти(Путь, "\", НаправлениеПоиска.СКонца);
ИмяФайла = Сред(Путь, Поз + 1); // "Продажи.xlsx"

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

Функция СтрНайти чувствительна к регистру: «Москва» и «москва» для неё — разные строки. Если регистр не важен, приведите обе строки к одному регистру с помощью ВРег() или НРег():

Текст = "Счёт на ОПЛАТУ № 15";

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

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

КонецЕсли;

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

Типичные ошибки
01
Не проверяется результат на 0: позиция 0 передаётся в Сред() или Лев(), и программа получает пустые или неверные данные
02
Поиск без приведения регистра: из-за разного регистра букв совпадение не находится, хотя визуально строки одинаковы
03
СтрНайти с пустой подстрокой поиска: поведение неочевидно, перед вызовом стоит проверить, что искомая строка не пуста
04
Использование СтрНайти там, где нужно простое сравнение: для точного совпадения строк достаточно оператора =

Как найти все вхождения символа

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

Строка = "1;2;3;4";

Счетчик = 0;

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

Пока Позиция > 0 Цикл

Счетчик = Счетчик + 1;

Позиция = СтрНайти(Строка, ";", , Позиция + 1);

КонецЦикла;

// Счетчик = 3

Обратите внимание на две запятые подряд в вызове: третий параметр (НаправлениеПоиска) пропущен, чтобы задать четвёртый. Это стандартный приём пропуска необязательных параметров во встроенном языке.

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

Типовой порядок разбора строки
  1. 1
    Проверьте, что исходная строка не пустая: ПустаяСтрока(Строка)
  2. 2
    Найдите позицию разделителя через СтрНайти()
  3. 3
    Проверьте, что результат больше 0
  4. 4
    Извлеките нужную часть через Лев(), Сред() или Прав()
  5. 5
    При необходимости продолжите поиск с позиции + 1

Практические сценарии использования

Разбор ФИО на части

Строка «Иванов Иван Иванович» разбирается поиском пробелов: первый пробел отделяет фамилию, второй — имя от отчества. Позицию второго пробела получают либо через НачальнуюПозицию, либо через НомерВхождения = 2.

Проверка формата номера документа

Если нужно убедиться, что номер содержит префикс и разделитель, достаточно проверить СтрНайти(Номер, "-") > 0. Для более строгой проверки позицию сравнивают с ожидаемой длиной префикса.

Извлечение значения из строки вида «ключ=значение»

Ищется позиция знака «=», затем значение берётся как Сред(Строка, Позиция + 1), а ключ — как Лев(Строка, Позиция - 1). Такой приём часто используется при разборе строк из файлов обмена и логов.

Чем искать в строке

СтрНайти()

Основной способ: возвращает позицию символа или подстроки. Подходит для разбора и проверок

СтрРазделить()

Когда нужно не найти позицию, а сразу получить массив частей по разделителю

СтрЧислоВхождений()

Когда нужно только количество вхождений подстроки без позиций

Оператор = или Подобно в запросе

Для точного сравнения строк или поиска по шаблону в запросах к базе данных

Проверка результата и отладка

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

Частая причина «неработающего» поиска — неразрывные пробелы и символы табуляции, которые визуально неотличимы от обычных пробелов. Такие символы имеют другие коды, поэтому СтрНайти по обычному пробелу их не находит. Перед поиском строку можно нормализовать, заменив неразрывный пробел (Символ(160)) на обычный.

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

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

Значение, возвращённое СтрНайти
Норма

Число от 1 до длины строки

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

0 — вхождение не найдено, дальнейшая обработка без проверки даст ошибку логики

Извлечённая подстрока
Норма

Совпадает с ожидаемым фрагментом без лишних символов по краям

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

Пустая строка или захвачен разделитель — неверно рассчитана позиция

Поиск по реальным данным
Норма

Находит все ожидаемые варианты регистра и написания

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

Часть данных пропускается — вероятно, проблема регистра или неразрывных пробелов

Итог

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

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

Часто задаваемые вопросы

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

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

Как проверить, содержит ли строка подстроку?

Достаточно условия вида Если СтрНайти(Строка, Подстрока) > 0 Тогда. Сама позиция при этом не нужна — важен только факт наличия вхождения.

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

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

Как найти позицию второго или третьего вхождения?

Передайте номер вхождения пятым параметром: СтрНайти(Строка, "-", , , 2) вернёт позицию второго дефиса. Либо начните поиск с позиции, следующей за предыдущим найденным вхождением.

Можно ли искать по шаблону, например «любые цифры»?

СтрНайти работает только с точным совпадением. Для поиска по шаблону в запросах используется оператор ПОДОБНО, а в коде приходится перебирать символы в цикле и проверять каждый через сравнение или КодСимвола().

Что вернёт СтрНайти, если искать пустую строку?

Поведение при пустой подстроке поиска неочевидно и зависит от платформы, поэтому полагаться на него не стоит. Перед вызовом проверяйте искомое значение через ПустаяСтрока() и обрабатывайте этот случай отдельно.