Разработка и Конфигурация · 13 мин
Как найти символы в строке в 1С
Как найти символы в строке в 1С: функции Найти и СтрНайти, поиск с учётом регистра, все вхождения подстроки, проверка наличия символа и типичные ошибки разработчиков.
Поиск символов и подстрок — одна из самых частых операций при работе со строками в 1С. Она нужна при разборе наименований товаров, проверке форматов артикулов, разделении ФИО, анализе путей к файлам и десятках других задач. Встроенный язык 1С предоставляет для этого несколько функций, и правильный выбор зависит от версии платформы и конкретной задачи.
Ключевое, что нужно понимать сразу: нумерация символов в строках 1С начинается с единицы, а не с нуля, как во многих других языках. Если функция поиска вернула 0 — это означает, что совпадение не найдено, а не что символ находится в начале строки. Именно на этом нюансе чаще всего ошибаются начинающие разработчики.
Ниже разобраны основные и вспомогательные функции поиска, приёмы поиска без учёта регистра, способы найти все вхождения подстроки и типичные ошибки с готовыми примерами кода.
Функция Найти() — базовый способ поиска подстроки
Функция Найти(Строка, Подстрока) ищет первое вхождение подстроки в строку и возвращает позицию первого символа найденного фрагмента. Если совпадений нет, возвращается 0. Функция работает на всех версиях платформы 1С:Предприятие 8 и остаётся самым распространённым способом поиска в типовых конфигурациях.
Строка = "Номенклатура: Кабель ВВГнг 3х2.5";
Позиция = Найти(Строка, "Кабель");
// Позиция = 15
Позиция = Найти(Строка, "Провод");
// Позиция = 0 — подстрока не найдена
Важная особенность: поиск выполняется с учётом регистра. Вызов Найти("Кабель ВВГ", "кабель") вернёт 0, потому что «К» и «к» — разные символы. Это частая причина «непонятных» ситуаций, когда подстрока визуально присутствует в строке, но функция её не находит.
Функцию удобно использовать в условиях для проверки наличия подстроки:
Если Найти(Наименование, "(б/у)") > 0 Тогда
// Товар помечен как бывший в употреблении
КонецЕсли;
Функция СтрНайти() — расширенные возможности поиска
Функция СтрНайти() появилась как современная замена Найти() и поддерживает дополнительные параметры: направление поиска, начальную позицию и номер искомого вхождения. Полный синтаксис:
СтрНайти(Строка, ПодстрокаПоиска, НаправлениеПоиска, НачальнаяПозиция, НомерВхождения)
Параметр НаправлениеПоиска принимает значения НаправлениеПоиска.СНачала или НаправлениеПоиска.СКонца. Поиск с конца полезен, когда нужно найти последний разделитель — например, точку перед расширением файла:
ИмяФайла = "отчет.продажи.январь.pdf";
ПозицияТочки = СтрНайти(ИмяФайла, ".", НаправлениеПоиска.СКонца);
Расширение = Сред(ИмяФайла, ПозицияТочки + 1); // "pdf"
Параметр НачальнаяПозиция задаёт символ, с которого начинается поиск, а НомерВхождения позволяет получить позицию второго, третьего и последующих совпадений без цикла:
Строка = "Иванов;Петров;Сидоров";
ВторойРазделитель = СтрНайти(Строка, ";", , , 2);
// ВторойРазделитель = 14
Найти или СтрНайти
Подходит для простого поиска первого вхождения и для кода, который должен работать на любых версиях платформы. Ограничение — нет поиска с конца и номера вхождения.
Подходит для новых разработок: поиск с конца, с заданной позиции, по номеру вхождения. Ограничение — недоступна в очень старых релизах платформы 8.2 и ранних 8.3.
Поиск без учёта регистра
Встроенных функций поиска без учёта регистра в языке 1С нет, поэтому стандартный приём — привести обе строки к одному регистру перед сравнением. Для этого используются функции ВРег() (верхний регистр) или НРег() (нижний регистр):
Наименование = "Кабель ВВГнг 3х2.5";
Если Найти(ВРег(Наименование), ВРег("кабель")) > 0 Тогда
// Совпадение найдено независимо от регистра
КонецЕсли;
При таком подходе помните о двух ограничениях. Во-первых, найденная позиция относится к преобразованной строке — если дальше нужно извлечь фрагмент из исходной строки с сохранением регистра, позиция останется корректной, так как ВРег() не меняет длину строки. Во-вторых, для очень больших строк двойное преобразование регистра даёт дополнительные затраты памяти, что имеет значение в массовых обработках.
Проверка наличия одного символа из набора
Когда нужно проверить, содержит ли строка хотя бы один символ из заданного набора (например, запрещённые в артикуле знаки), удобно перебрать набор в цикле:
ЗапрещенныеСимволы = "\/:*?""<>|";
ЕстьЗапрещенные = Ложь;
Для Позиция = 1 По СтрДлина(ЗапрещенныеСимволы) Цикл
Если Найти(Артикул, Сред(ЗапрещенныеСимволы, Позиция, 1)) > 0 Тогда
ЕстьЗапрещенные = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Как найти все вхождения подстроки в строку
Стандартная задача — подсчитать количество вхождений или найти позиции всех совпадений. Решается циклом со смещением начальной позиции поиска:
Строка = "1;2;3;4;5";
Подстрока = ";";
КоличествоВхождений = 0;
НачальнаяПозиция = 1;
Позиция = СтрНайти(Строка, Подстрока, , НачальнаяПозиция);
Пока Позиция > 0 Цикл
КоличествоВхождений = КоличествоВхождений + 1;
НачальнаяПозиция = Позиция + СтрДлина(Подстрока);
Позиция = СтрНайти(Строка, Подстрока, , НачальнаяПозиция);
КонецЦикла;
// КоличествоВхождений = 4
Если цель — разбить строку по разделителю, вместо ручного поиска всех вхождений проще использовать СтрРазделить(Строка, ";"), которая вернёт массив частей. Для обратной операции есть СтрСоединить(). Это избавляет от написания цикла и снижает риск ошибок.
Подсчёт вхождений через СтрЧислоВхождений
Для простого подсчёта количества вхождений подстроки есть отдельная функция СтрЧислоВхождений(Строка, Подстрока). Она возвращает число непересекающихся вхождений и избавляет от написания цикла в простых сценариях:
КоличествоЗапятых = СтрЧислоВхождений("а,б,в,г", ","); // 3
Проверка и обработка найденных символов
После поиска результат почти всегда используется для извлечения или замены фрагмента. Основные сопутствующие функции:
Лев(Строка, N)— взять N символов слева;Прав(Строка, N)— взять N символов справа;Сред(Строка, Позиция, Длина)— извлечь фрагмент с указанной позиции;СтрЗаменить(Строка, Что, НаЧто)— заменить все вхождения подстроки;СокрЛП(Строка)— убрать незначащие пробелы по краям.
Типовой пример — разбор строки вида «Фамилия Имя Отчество» по первому пробелу:
ФИО = "Иванов Сергей Петрович";
ПозицияПробела = Найти(ФИО, " ");
Если ПозицияПробела > 0 Тогда
Фамилия = Лев(ФИО, ПозицияПробела - 1);
Остаток = Сред(ФИО, ПозицияПробела + 1);
Иначе
Фамилия = ФИО; // пробела нет — вся строка является фамилией
КонецЕсли;
Обратите внимание на ветку Иначе: обработка ситуации «подстрока не найдена» обязательна. Если её опустить и сразу вызвать Лев(ФИО, ПозицияПробела - 1), при нулевой позиции получите Лев(ФИО, -1) — пустую строку или ошибку в зависимости от контекста, и данные будут потеряны без видимого сообщения.
- 1Определите искомую подстроку и проверьте, что она не пустая
- 2Вызовите Найти() или СтрНайти() и сохраните позицию в переменную
- 3Проверьте, что позиция больше 0 — совпадение действительно найдено
- 4Извлеките фрагмент через Лев(), Сред() или Прав() с учётом длины подстроки
- 5Предусмотрите ветку на случай отсутствия совпадения
- 6Проверьте результат на тестовых строках: с совпадением, без него, с совпадением в начале и в конце строки
Частые ошибки при поиске символов в строке
Первая и самая массовая ошибка — сравнение результата поиска с Неопределено или NULL. Функции поиска в 1С всегда возвращают число, поэтому корректная проверка — только Если Позиция > 0 Тогда или Если Позиция = 0 Тогда.
Вторая ошибка — игнорирование регистра и неразрывных пробелов. Строки из Excel или внешних систем часто содержат неразрывный пробел (символ с кодом 160) вместо обычного. Визуально строки одинаковы, но Найти(Строка, " ") вернёт 0. Решение — предварительно заменить символ 160 на обычный пробел через СтрЗаменить(Строка, Символ(160), " ").
Третья ошибка — поиск в строке, где могут быть лишние пробелы по краям. Перед анализом строк из пользовательского ввода всегда применяйте СокрЛП(), иначе проверка «строка начинается с префикса» даст ложноотрицательный результат.
Альтернативные способы: шаблоны и регулярные выражения
Когда нужно не просто найти подстроку, а проверить строку на соответствие шаблону (например, «начинается с букв АРТ, далее цифры»), простого поиска недостаточно. В чистом встроенном языке 1С полноценных регулярных выражений нет, поэтому применяют несколько обходных путей.
Первый — комбинация СтрНачинаетсяС(), СтрЗаканчиваетсяНа() и посимвольной проверки через Сред() и сравнение кодов символов. Второй — использование COM-объекта VBScript.RegExp на Windows-сервере, что даёт настоящие регулярные выражения, но привязывает решение к Windows-окружению и недоступно на Linux и в мобильной платформе. Третий — внешние компоненты и библиотеки общего назначения, если политика проекта это допускает.
Как выбрать способ поиска
Для большинства прикладных задач в учётных системах достаточно связки СтрНайти(), СтрРазделить() и СтрЗаменить(). Регулярные выражения оправданы только при разборе сложных форматов — например, валидации номеров документов с переменной структурой.
Как проверить корректность кода поиска
Код корректно обрабатывает позицию 0 и не падает с ошибкой
При отсутствии совпадения возникает исключение или пустые данные записываются в базу
Совпадение в самом начале (позиция 1) и в самом конце строки обрабатывается правильно
Первый или последний символ теряется при извлечении фрагмента
Поиск находит подстроку независимо от регистра и лишних пробелов, если это требуется
Одинаковые по смыслу строки дают разный результат
Цикл завершается и возвращает корректное число совпадений
Зависание сеанса или пропуск пересекающихся вхождений
Частые вопросы
Почему Найти() возвращает 0, хотя подстрока точно есть в строке?
Три наиболее вероятные причины: разный регистр букв (поиск чувствителен к регистру), неразрывный пробел (символ 160) вместо обычного в данных из внешних источников, лишние пробелы или невидимые управляющие символы. Приведите строки к одному регистру, замените символ 160 и примените СокрЛП() перед поиском.
Чем СтрНайти() отличается от Найти() и что выбрать?
СтрНайти() поддерживает направление поиска (с начала или с конца), начальную позицию и номер вхождения, тогда как Найти() ищет только первое вхождение с начала строки. Для нового кода рекомендуется СтрНайти(); Найти() уместна в доработках старых конфигураций, где важна совместимость.
Как проверить, что строка начинается с определённых символов?
Используйте функцию СтрНачинаетсяС(Строка, Подстрока) — она возвращает Истина или Ложь и читается лучше, чем сравнение Найти(Строка, Подстрока) = 1. Для конца строки есть аналогичная СтрЗаканчиваетсяНа().
Как найти позицию второго или третьего вхождения подстроки?
Передайте номер вхождения пятым параметром СтрНайти(): СтрНайти(Строка, ";", , , 2) вернёт позицию второго разделителя. Альтернатива — цикл со смещением начальной позиции за пределы предыдущего совпадения.
Есть ли в 1С поиск по регулярным выражениям?
Во встроенном языке полноценной поддержки регулярных выражений нет. На Windows можно использовать COM-объект VBScript.RegExp, но решение не будет работать на Linux-сервере и мобильной платформе. Для кроссплатформенных сценариев шаблон проверяют комбинацией строковых функций или подключают внешние компоненты.
Как заменить найденный символ на другой?
Используйте СтрЗаменить(Строка, ЧтоЗаменить, НаЧтоЗаменить) — функция заменит все вхождения сразу, отдельный поиск позиции не нужен. Если заменить требуется только первое вхождение, найдите его позицию через СтрНайти() и соберите новую строку из Лев(), замены и Сред().
Что важно запомнить
Найти() и СтрНайти() возвращают позицию с единицы или 0 при отсутствии совпадения — проверяйте результат именно на 0. Поиск всегда чувствителен к регистру: приводите строки к одному регистру через ВРег(). Для сложных сценариев используйте параметры СтрНайти() (направление, начальная позиция, номер вхождения), а для разбиения строк — СтрРазделить(). Перед поиском во внешних данных убирайте неразрывные пробелы и лишние пробелы по краям.