Разработка и Конфигурация · 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.
Поиск с заданной позиции и в обратном направлении
Поиск не с начала строки
Параметр «НачальнаяПозиция» в СтрНайти() позволяет начать поиск не с первого символа. Это удобно, когда нужно найти следующее вхождение после уже найденного:
Строка = "а.б.в.г";
Первая = СтрНайти(Строка, "."); // 2
Вторая = СтрНайти(Строка, ".", , Первая + 1); // 4
Третий параметр (направление) пропускается двумя запятыми подряд — это стандартный приём пропуска необязательных параметров во встроенном языке.
Поиск последнего вхождения
Если нужна не первая, а последняя позиция символа (например, последний разделитель в пути к файлу), задайте направление поиска НаправлениеПоиска.СКонца:
Путь = "С:\Документы\Отчеты\файл.txt";
Позиция = СтрНайти(Путь, "\", НаправлениеПоиска.СКонца);
ИмяФайла = Сред(Путь, Позиция + 1); // "файл.txt"
Формально это уже не «первое вхождение», но приём настолько часто нужен рядом с основной задачей, что его стоит держать в памяти.
Практический пример: извлечение части строки до символа
Самый частый сценарий на практике — не просто узнать позицию, а отрезать часть строки до или после найденного символа. Связка СтрНайти() с функциями Лев(), Сред() и Прав() решает почти все такие задачи.
СтрокаКода = "ТОВ-00012345";
Позиция = СтрНайти(СтрокаКода, "-");
Если Позиция > 0 Тогда
Префикс = Лев(СтрокаКода, Позиция - 1); // "ТОВ"
Номер = Сред(СтрокаКода, Позиция + 1); // "00012345"
КонецЕсли;
Обратите внимание на арифметику: Лев(Строка, Позиция - 1) берёт символы строго до разделителя, а Сред(Строка, Позиция + 1) — всё после него, пропуская сам разделитель. Забытые «плюс один» и «минус один» — самая частая причина «лишних» символов в результате.
- 1Определите символ-разделитель и убедитесь, что он действительно присутствует в данных.
- 2Выполните Позиция = СтрНайти(Строка, Разделитель).
- 3Проверьте Позиция > 0 — иначе разделителя нет, и строку нужно обработать целиком.
- 4Извлеките левую часть через Лев(Строка, Позиция - 1) и правую через Сред(Строка, Позиция + 1).
- 5Проверьте результат на контрольном примере, включая строку без разделителя.
Альтернативы: когда СтрНайти не лучший выбор
Если строка содержит много одинаковых разделителей и нужны все части сразу, удобнее СтрРазделить() — она вернёт массив подстрок без ручного поиска позиций. Для проверки самого факта «символ есть в строке» без необходимости знать позицию достаточно той же СтрНайти() в связке с простым условием.
Для сложных шаблонов (цифры, несколько возможных разделителей, структура вида «ключ=значение») в толстом клиенте и на сервере доступны регулярные выражения через COM-объект VBScript.RegExp на Windows, но это тяжеловесное решение с ограничениями по кроссплатформенности. Для одиночного символа оно не нужно — СтрНайти() быстрее и проще.
Как выбрать подход
Отладка и проверка результата
При отладке поиска в конфигураторе поставьте точку останова сразу после вызова функции и посмотрите значение позиции в табло. Полезно одновременно вывести саму строку через Сообщить(), потому что невидимые символы — неразрывные пробелы, табуляции, переносы строк — частая причина «не находится то, что на экране есть».
Особенно коварны строки, загруженные из Excel, CSV или веб-сервисов: визуально обычный пробел может оказаться неразрывным пробелом (код 160), и СтрНайти(Строка, " ") его не найдёт. В таких случаях помогает предварительная замена СтрЗаменить(Строка, Символ(160), " ").
Как проверить результат
Число от 1 до длины строки
0 — символ не найден, ветку обработки нужно предусмотреть
Не содержит самого разделителя
Разделитель попал в результат — проверьте ±1 в Лев() или Сред()
Символ находится на ожидаемой позиции
Позиция 0 при визуально видимом символе — проверьте неразрывные пробелы и регистр
Частые вопросы
Чем СтрНайти отличается от Найти?
Обе функции ищут подстроку и возвращают позицию или 0. СтрНайти появилась в платформе 8.3.6 и поддерживает направление поиска, начальную позицию и номер вхождения; Найти имеет только два параметра. Для нового кода рекомендуется СтрНайти.
Что вернёт функция, если символа нет в строке?
Число 0. Не пустая строка и не Неопределено — именно число, поэтому проверка всегда выглядит как «Если Позиция > 0 Тогда».
Как найти символ без учёта регистра?
Приведите обе строки к одному регистру перед поиском: СтрНайти(ВРег(Строка), ВРег(Подстрока)). Учтите, что позиция останется корректной, так как смена регистра не меняет длину строки.
Как найти второе или третье вхождение символа?
Используйте пятый параметр СтрНайти — номер вхождения: СтрНайти(Строка, ";", , , 2) вернёт позицию второго разделителя. Альтернатива — повторный поиск с начальной позицией после предыдущего совпадения.
Почему функция не находит пробел, который виден в строке?
Скорее всего, это неразрывный пробел (код 160) или табуляция, попавшие в данные при импорте. Проверьте код символа через КодСимвола() или предварительно замените такие символы обычными пробелами через СтрЗаменить.
Можно ли искать сразу несколько разных символов?
Одним вызовом — нет, функция ищет одну подстроку. Выполните поиск по каждому символу отдельно и возьмите минимальную ненулевую позицию, либо используйте регулярные выражения, если конфигурация и режим работы это позволяют.
Что важно запомнить
Первое вхождение символа ищется через СтрНайти(Строка, Символ) или Найти() в старом коде; результат — позиция от 1 или 0 при отсутствии совпадения. Всегда проверяйте результат на ноль, помните про регистрозависимость и невидимые символы в импортированных данных, а для извлечения частей строки комбинируйте поиск с Лев() и Сред() с корректной арифметикой ±1.