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

Разработка и Конфигурация · 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. 1
    Определите искомую подстроку и проверьте, что она не пустая
  2. 2
    Вызовите Найти() или СтрНайти() и сохраните позицию в переменную
  3. 3
    Проверьте, что позиция больше 0 — совпадение действительно найдено
  4. 4
    Извлеките фрагмент через Лев(), Сред() или Прав() с учётом длины подстроки
  5. 5
    Предусмотрите ветку на случай отсутствия совпадения
  6. 6
    Проверьте результат на тестовых строках: с совпадением, без него, с совпадением в начале и в конце строки

Частые ошибки при поиске символов в строке

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

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

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

Типичные ошибки при поиске в строках 1С
01
Сравнение результата Найти() с Неопределено вместо проверки на 0 — условие никогда не сработает корректно
02
Поиск без учёта того, что функция чувствительна к регистру, — подстрока «не находится», хотя визуально она есть
03
Игнорирование неразрывного пробела (символ 160) в данных из Excel — поиск по обычному пробелу возвращает 0
04
Отсутствие ветки на случай Позиция = 0 — извлечение фрагмента даёт пустые или искажённые данные
05
Смещение позиции в цикле на 1 вместо длины подстроки — лишние совпадения или бесконечный цикл

Альтернативные способы: шаблоны и регулярные выражения

Когда нужно не просто найти подстроку, а проверить строку на соответствие шаблону (например, «начинается с букв АРТ, далее цифры»), простого поиска недостаточно. В чистом встроенном языке 1С полноценных регулярных выражений нет, поэтому применяют несколько обходных путей.

Первый — комбинация СтрНачинаетсяС(), СтрЗаканчиваетсяНа() и посимвольной проверки через Сред() и сравнение кодов символов. Второй — использование COM-объекта VBScript.RegExp на Windows-сервере, что даёт настоящие регулярные выражения, но привязывает решение к Windows-окружению и недоступно на Linux и в мобильной платформе. Третий — внешние компоненты и библиотеки общего назначения, если политика проекта это допускает.

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

Как выбрать способ поиска

Нужно найти первое вхождение простой подстрокиИспользуйте Найти() или СтрНайти() без дополнительных параметров
Нужно найти последний разделитель или вхождение с конца строкиИспользуйте СтрНайти() с параметром НаправлениеПоиска.СКонца
Регистр букв не должен влиять на результатПриведите обе строки к одному регистру через ВРег() перед поиском
Нужно разбить строку по разделителюИспользуйте СтрРазделить() вместо цикла поиска
Нужно проверить сложный шаблон с вариативными символамиРассмотрите COM-объект VBScript.RegExp на Windows или внешнюю компоненту
Строка пришла из Excel или внешней системыСначала замените символ 160 на обычный пробел и примените СокрЛП()

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

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

Как проверить корректность кода поиска

Поведение при отсутствии подстроки
Норма

Код корректно обрабатывает позицию 0 и не падает с ошибкой

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

При отсутствии совпадения возникает исключение или пустые данные записываются в базу

Граничные позиции
Норма

Совпадение в самом начале (позиция 1) и в самом конце строки обрабатывается правильно

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

Первый или последний символ теряется при извлечении фрагмента

Регистр и пробелы
Норма

Поиск находит подстроку независимо от регистра и лишних пробелов, если это требуется

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

Одинаковые по смыслу строки дают разный результат

Цикл поиска всех вхождений
Норма

Цикл завершается и возвращает корректное число совпадений

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

Зависание сеанса или пропуск пересекающихся вхождений

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

Почему Найти() возвращает 0, хотя подстрока точно есть в строке?

Три наиболее вероятные причины: разный регистр букв (поиск чувствителен к регистру), неразрывный пробел (символ 160) вместо обычного в данных из внешних источников, лишние пробелы или невидимые управляющие символы. Приведите строки к одному регистру, замените символ 160 и примените СокрЛП() перед поиском.

Чем СтрНайти() отличается от Найти() и что выбрать?

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

Как проверить, что строка начинается с определённых символов?

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

Как найти позицию второго или третьего вхождения подстроки?

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

Есть ли в 1С поиск по регулярным выражениям?

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

Как заменить найденный символ на другой?

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

Итог

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

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