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

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

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

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

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

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

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

Функция Найти() — классический способ

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

Строка = "Артикул: АБВ-12345";

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

// Позиция = 15

Функция ищет слева направо и останавливается на первом совпадении. Если искомый символ встречается несколько раз, вы получите позицию только самого первого из них — это и есть «первое вхождение» в строгом смысле.

Учитывайте, что поиск регистрозависимый: Найти("Абв", "а") вернёт 0, потому что заглавная «А» и строчная «а» — разные символы. Если регистр не важен, предварительно приведите обе строки к одному регистру через ВРег() или НРег().

Функция СтрНайти() — современный вариант

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

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

Строка = "кошка;собака;птица";

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

// Позиция = 6 — первый разделитель

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

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

Найти()

Подходит для поддержки старого кода и конфигураций на платформе ниже 8.3.6. Новых параметров нет, только простой поиск с начала строки.

СтрНайти()

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

Проверка результата: найден символ или нет

Главное правило работы с обеими функциями — всегда проверять результат перед использованием. Нулевая позиция означает, что символа в строке нет, и попытка вырезать подстроку по этой позиции приведёт к неверным данным или ошибке.

Позиция = СтрНайти(Наименование, ",");

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

Город = Лев(Наименование, Позиция - 1);

Иначе

Город = Наименование; // разделителя нет — берём строку целиком

КонецЕсли;

Типичная ошибка — сравнивать результат с пустой строкой или Неопределено. Функция возвращает число, поэтому корректная проверка — именно Позиция > 0 или Позиция = 0.

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

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

Поиск не с начала строки

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

Строка = "а.б.в.г";

Первая = СтрНайти(Строка, "."); // 2

Вторая = СтрНайти(Строка, ".", , Первая + 1); // 4

Третий параметр (направление) пропускается двумя запятыми подряд — это стандартный приём пропуска необязательных параметров во встроенном языке.

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

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

Путь = "С:\Документы\Отчеты\файл.txt";

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

ИмяФайла = Сред(Путь, Позиция + 1); // "файл.txt"

Формально это уже не «первое вхождение», но приём настолько часто нужен рядом с основной задачей, что его стоит держать в памяти.

Практический пример: извлечение части строки до символа

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

СтрокаКода = "ТОВ-00012345";

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

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

Префикс = Лев(СтрокаКода, Позиция - 1); // "ТОВ"

Номер = Сред(СтрокаКода, Позиция + 1); // "00012345"

КонецЕсли;

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

Порядок действий при разборе строки
  1. 1
    Определите символ-разделитель и убедитесь, что он действительно присутствует в данных.
  2. 2
    Выполните Позиция = СтрНайти(Строка, Разделитель).
  3. 3
    Проверьте Позиция > 0 — иначе разделителя нет, и строку нужно обработать целиком.
  4. 4
    Извлеките левую часть через Лев(Строка, Позиция - 1) и правую через Сред(Строка, Позиция + 1).
  5. 5
    Проверьте результат на контрольном примере, включая строку без разделителя.

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

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

Для сложных шаблонов (цифры, несколько возможных разделителей, структура вида «ключ=значение») в толстом клиенте и на сервере доступны регулярные выражения через COM-объект VBScript.RegExp на Windows, но это тяжеловесное решение с ограничениями по кроссплатформенности. Для одиночного символа оно не нужно — СтрНайти() быстрее и проще.

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

Как выбрать подход

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

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

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

Особенно коварны строки, загруженные из Excel, CSV или веб-сервисов: визуально обычный пробел может оказаться неразрывным пробелом (код 160), и СтрНайти(Строка, " ") его не найдёт. В таких случаях помогает предварительная замена СтрЗаменить(Строка, Символ(160), " ").

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

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

Возвращаемое значение
Норма

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

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

0 — символ не найден, ветку обработки нужно предусмотреть

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

Не содержит самого разделителя

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

Разделитель попал в результат — проверьте ±1 в Лев() или Сред()

Поиск в импортированных данных
Норма

Символ находится на ожидаемой позиции

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

Позиция 0 при визуально видимом символе — проверьте неразрывные пробелы и регистр

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

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

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

Что вернёт функция, если символа нет в строке?

Число 0. Не пустая строка и не Неопределено — именно число, поэтому проверка всегда выглядит как «Если Позиция > 0 Тогда».

Как найти символ без учёта регистра?

Приведите обе строки к одному регистру перед поиском: СтрНайти(ВРег(Строка), ВРег(Подстрока)). Учтите, что позиция останется корректной, так как смена регистра не меняет длину строки.

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

Используйте пятый параметр СтрНайти — номер вхождения: СтрНайти(Строка, ";", , , 2) вернёт позицию второго разделителя. Альтернатива — повторный поиск с начальной позицией после предыдущего совпадения.

Почему функция не находит пробел, который виден в строке?

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

Можно ли искать сразу несколько разных символов?

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

Итог

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

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