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

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

Как найти номер символа в строке в 1С

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

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

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

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

Функция СтрНайти: синтаксис и параметры

Основной инструмент поиска в современных версиях платформы — СтрНайти(). Полный синтаксис выглядит так:

Позиция = СтрНайти(Строка, ПодстрокаПоиска, НаправлениеПоиска, НачальнаяПозиция, НомерВхождения);

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

Результат — число: позиция первого символа найденного фрагмента. Например, СтрНайти("Артикул-12345", "-") вернёт 8, поскольку дефис стоит восьмым символом. Если искомого фрагмента нет, результат будет равен 0.

Простейший поиск позиции символа

Минимальный рабочий пример — найти одиночный символ, например разделитель в составном коде:

Код = "МСК-001-Склад";

ПозицияДефиса = СтрНайти(Код, "-");

// ПозицияДефиса = 4

Функция ищет точное совпадение с учётом регистра. Это значит, что СтрНайти("Склад", "с") вернёт 0, потому что строчная «с» не совпадает с заглавной «С». Для поиска без учёта регистра строку и подстроку предварительно приводят к одному регистру функциями ВРег() или НРег():

Позиция = СтрНайти(НРег(Наименование), НРег(ИскомыйТекст));

Учитывайте, что при таком приёме возвращаемая позиция остаётся корректной, поскольку смена регистра не меняет длину строки и порядок символов.

Поиск с конца строки и конкретное вхождение

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

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

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

// Позиция последней точки — перед "epf"

Если нужно не последнее, а, скажем, второе вхождение, используется пятый параметр — номер вхождения:

СтрокаКода = "А-Б-В-Г";

ВторойДефис = СтрНайти(СтрокаКода, "-", , , 2);

// Позиция второго дефиса

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

Как найти N-е вхождение разделителя
  1. 1
    Вызовите СтрНайти с начальными параметрами и получите первую позицию
  2. 2
    Проверьте, что результат больше 0 — вхождение существует
  3. 3
    Для следующего поиска передайте НачальнаяПозиция = найденная позиция + 1
  4. 4
    Повторяйте, пока функция не вернёт 0 или не будет найдено нужное вхождение

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

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

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

СтрНайти или Найти

СтрНайти

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

Найти

Устаревший аналог с двумя параметрами. Допустим только при правке legacy-кода, где важно минимизировать изменения.

Практические сценарии: извлечение части строки

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

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

Если ПозицияТочки > 0 Тогда

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

ИмяБезРасширения = Лев(ИмяФайла, ПозицияТочки - 1);

КонецЕсли;

Обратите внимание на арифметику: Сред(..., Позиция + 1) пропускает сам разделитель, а Лев(..., Позиция - 1) берёт всё до него. Смещение на единицу — самое частое место ошибки, особенно у тех, кто привык к нумерации с нуля в других языках.

Разбор строки с несколькими разделителями

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

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

Главное правило безопасного кода: перед использованием позиции всегда проверяйте, что она больше нуля. Вызов Сред(Строка, 0) или Лев(Строка, -1) при нулевой позиции приведёт либо к ошибке выполнения, либо к непредсказуемому результату в зависимости от контекста.

Типичные ошибки
01
Использование позиции без проверки на 0 — обрыв кода или пустые значения при отсутствии разделителя
02
Ожидание нумерации с нуля — в 1С первый символ имеет позицию 1, смещения считаются иначе
03
Поиск без учёта регистра там, где данные вводятся вручную, — вхождение не находится
04
Использование СтрНайти для строк с множеством разделителей вместо СтрРазделить — громоздкий и хрупкий код

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

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

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

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

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

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

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

Позиция разделителя внутри строки
Норма

Больше 1 и меньше длины строки — обе части непустые

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

1 или равна длине — одна из частей окажется пустой

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

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

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

Разделитель попал в результат — ошибка смещения на единицу

Альтернативы: когда СтрНайти недостаточно

Для сложных шаблонов — например, проверки, что строка соответствует маске кода или содержит число в определённом формате — простого поиска подстроки мало. В таких задачах применяют регулярные выражения через COM-объект VBScript.RegExp на Windows либо перебор символов в цикле с посимвольным анализом.

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

Итог

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

Позицию символа возвращает СтрНайти, нумерация с 1, отсутствие вхождения — 0. Для поиска с конца и N-го вхождения используйте дополнительные параметры. Всегда проверяйте результат перед передачей в Лев, Сред или Прав.

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

Что возвращает СтрНайти, если символ не найден?

Функция возвращает число 0. Это единственный признак отсутствия вхождения, поэтому перед использованием позиции в функциях Лев, Сред или Прав результат нужно проверить условием «больше нуля», иначе возможен обрыв выполнения кода.

С какого числа начинается нумерация символов в 1С?

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

Как найти последнее вхождение символа в строку?

Передайте в СтрНайти третий параметр — НаправлениеПоискаСтроки.СКонца. Функция начнёт поиск с конца строки и вернёт позицию последнего вхождения, что удобно для отделения расширения файла или последнего сегмента пути.

Учитывает ли СтрНайти регистр букв?

Да, сравнение выполняется посимвольно с учётом регистра. Если регистр данных непредсказуем (например, ручной ввод пользователя), приведите обе строки к одному регистру функциями ВРег() или НРег() перед поиском.

Чем заменить СтрНайти, если разделителей в строке много?

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