Разработка и Конфигурация · 9 мин
Как найти номер символа в строке в 1С
Как найти позицию символа или подстроки в строке 1С: функции СтрНайти и Найти, направление поиска, номер вхождения, обработка нулевого результата и типовые ошибки.
Поиск позиции символа или подстроки внутри строки — одна из базовых операций при разработке на встроенном языке 1С. Она нужна при разборе наименований, кодов номенклатуры, путей к файлам, ответов веб-сервисов и любых данных, где структура зашита в текст. Во встроенном языке для этого есть функция СтрНайти(), а в устаревших конфигурациях встречается её предшественница — Найти().
Обе функции возвращают номер позиции, с которой начинается искомая подстрока. Нумерация символов в 1С начинается с единицы, а не с нуля, как во многих других языках. Если вхождение не найдено, функция возвращает 0 — это ключевой признак, по которому строится проверка результата.
Ниже разобраны синтаксис, режимы поиска, практические сценарии (извлечение части строки, поиск последнего вхождения, разбор составных кодов), а также типичные ошибки, которые приводят к неверным результатам или обрыву кода.
Функция СтрНайти: синтаксис и параметры
Основной инструмент поиска в современных версиях платформы — СтрНайти(). Полный синтаксис выглядит так:
Позиция = СтрНайти(Строка, ПодстрокаПоиска, НаправлениеПоиска, НачальнаяПозиция, НомерВхождения);
Обязательны только первые два параметра. Строка — исходный текст, ПодстрокаПоиска — искомый символ или фрагмент. Остальные параметры управляют тонкой настройкой: НаправлениеПоиска (СНачала или СКонца), НачальнаяПозиция — с какого символа начинать поиск, НомерВхождения — какое по счёту совпадение вернуть.
Результат — число: позиция первого символа найденного фрагмента. Например, СтрНайти("Артикул-12345", "-") вернёт 8, поскольку дефис стоит восьмым символом. Если искомого фрагмента нет, результат будет равен 0.
Простейший поиск позиции символа
Минимальный рабочий пример — найти одиночный символ, например разделитель в составном коде:
Код = "МСК-001-Склад";
ПозицияДефиса = СтрНайти(Код, "-");
// ПозицияДефиса = 4
Функция ищет точное совпадение с учётом регистра. Это значит, что СтрНайти("Склад", "с") вернёт 0, потому что строчная «с» не совпадает с заглавной «С». Для поиска без учёта регистра строку и подстроку предварительно приводят к одному регистру функциями ВРег() или НРег():
Позиция = СтрНайти(НРег(Наименование), НРег(ИскомыйТекст));
Учитывайте, что при таком приёме возвращаемая позиция остаётся корректной, поскольку смена регистра не меняет длину строки и порядок символов.
Поиск с конца строки и конкретное вхождение
Когда символ встречается несколько раз, базового вызова недостаточно. Типовая задача — найти последний разделитель, например точку перед расширением файла или последний слеш в пути. Здесь помогает параметр направления поиска:
ИмяФайла = "Отчет.Продажи.Итоговый.epf";
ПозицияТочки = СтрНайти(ИмяФайла, ".", НаправлениеПоискаСтроки.СКонца);
// Позиция последней точки — перед "epf"
Если нужно не последнее, а, скажем, второе вхождение, используется пятый параметр — номер вхождения:
СтрокаКода = "А-Б-В-Г";
ВторойДефис = СтрНайти(СтрокаКода, "-", , , 2);
// Позиция второго дефиса
Четвёртый параметр — начальная позиция — полезен, когда поиск нужно вести не с начала строки, а после уже найденного фрагмента. Это стандартный приём при последовательном разборе строки с несколькими одинаковыми разделителями: каждый следующий поиск начинается с позиции ПредыдущаяПозиция + 1.
- 1Вызовите СтрНайти с начальными параметрами и получите первую позицию
- 2Проверьте, что результат больше 0 — вхождение существует
- 3Для следующего поиска передайте НачальнаяПозиция = найденная позиция + 1
- 4Повторяйте, пока функция не вернёт 0 или не будет найдено нужное вхождение
Устаревшая функция Найти и совместимость
В старых конфигурациях и внешних обработках часто встречается функция Найти(Строка, Подстрока). Она принимает только два параметра и всегда ищет первое вхождение с начала строки. Результат идентичен вызову СтрНайти без дополнительных параметров.
Платформа поддерживает Найти() ради обратной совместимости, но в новом коде рекомендуется СтрНайти(): она функциональнее и соответствует актуальным стандартам разработки. При доработке старых модулей имеет смысл заменять вызовы постепенно, проверяя, не зависит ли логика от особенностей окружения.
СтрНайти или Найти
Рекомендуемый вариант: поддерживает направление поиска, начальную позицию и номер вхождения. Подходит для любого нового кода.
Устаревший аналог с двумя параметрами. Допустим только при правке legacy-кода, где важно минимизировать изменения.
Практические сценарии: извлечение части строки
Само по себе знание позиции редко является конечной целью — обычно по ней строку режут на части функциями Лев(), Прав(), Сред(). Классический пример — отделить расширение файла:
ПозицияТочки = СтрНайти(ИмяФайла, ".", НаправлениеПоискаСтроки.СКонца);
Если ПозицияТочки > 0 Тогда
Расширение = Сред(ИмяФайла, ПозицияТочки + 1);
ИмяБезРасширения = Лев(ИмяФайла, ПозицияТочки - 1);
КонецЕсли;
Обратите внимание на арифметику: Сред(..., Позиция + 1) пропускает сам разделитель, а Лев(..., Позиция - 1) берёт всё до него. Смещение на единицу — самое частое место ошибки, особенно у тех, кто привык к нумерации с нуля в других языках.
Разбор строки с несколькими разделителями
Если строка содержит много однотипных разделителей (CSV-подобные данные, составные коды), вручную искать каждую позицию неудобно. Для таких случаев практичнее СтрРазделить(), которая сразу возвращает массив частей. СтрНайти() оправдана, когда разделителей один-два или когда позиция нужна сама по себе — например, для проверки формата строки.
Проверка результата и обработка ошибок
Главное правило безопасного кода: перед использованием позиции всегда проверяйте, что она больше нуля. Вызов Сред(Строка, 0) или Лев(Строка, -1) при нулевой позиции приведёт либо к ошибке выполнения, либо к непредсказуемому результату в зависимости от контекста.
Также проверяйте граничные случаи: разделитель может стоять первым или последним символом строки. Тогда Лев(Строка, Позиция - 1) вернёт пустую строку, что часто является корректным результатом, но об этом стоит помнить при дальнейшей логике.
Как проверить результат поиска
Число от 1 до длины строки
0 — вхождение не найдено, результат нельзя использовать как позицию
Больше 1 и меньше длины строки — обе части непустые
1 или равна длине — одна из частей окажется пустой
Совпадает с ожидаемым фрагментом без разделителя на краю
Разделитель попал в результат — ошибка смещения на единицу
Альтернативы: когда СтрНайти недостаточно
Для сложных шаблонов — например, проверки, что строка соответствует маске кода или содержит число в определённом формате — простого поиска подстроки мало. В таких задачах применяют регулярные выражения через COM-объект VBScript.RegExp на Windows либо перебор символов в цикле с посимвольным анализом.
Если задача — не найти позицию, а проверить сам факт вхождения подстроки, код читается лучше с явным сравнением: Если СтрНайти(Строка, Подстрока) > 0 Тогда .... Это стандартная идиома, понятная любому разработчику 1С.
Что важно запомнить
Позицию символа возвращает СтрНайти, нумерация с 1, отсутствие вхождения — 0. Для поиска с конца и N-го вхождения используйте дополнительные параметры. Всегда проверяйте результат перед передачей в Лев, Сред или Прав.
Частые вопросы
Что возвращает СтрНайти, если символ не найден?
Функция возвращает число 0. Это единственный признак отсутствия вхождения, поэтому перед использованием позиции в функциях Лев, Сред или Прав результат нужно проверить условием «больше нуля», иначе возможен обрыв выполнения кода.
С какого числа начинается нумерация символов в 1С?
С единицы. Первый символ строки имеет позицию 1. Это отличается от C-подобных языков, где индексация идёт с нуля, поэтому при переносе алгоритмов из других языков все смещения нужно пересчитывать.
Как найти последнее вхождение символа в строку?
Передайте в СтрНайти третий параметр — НаправлениеПоискаСтроки.СКонца. Функция начнёт поиск с конца строки и вернёт позицию последнего вхождения, что удобно для отделения расширения файла или последнего сегмента пути.
Учитывает ли СтрНайти регистр букв?
Да, сравнение выполняется посимвольно с учётом регистра. Если регистр данных непредсказуем (например, ручной ввод пользователя), приведите обе строки к одному регистру функциями ВРег() или НРег() перед поиском.
Чем заменить СтрНайти, если разделителей в строке много?
Используйте СтрРазделить(Строка, Разделитель) — она возвращает массив частей сразу, без ручного поиска каждой позиции. СтрНайти остаётся уместной для одного-двух разделителей или когда нужна сама позиция, а не части строки.