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

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

Что такое подстрока в 1С и как с ней работать

Подстрока в 1С — часть строки, извлекаемая функциями Лев, Прав, Сред. Синтаксис, примеры кода, поиск подстроки, типичные ошибки и ответы на вопросы.

Подстрока в 1С — это часть строки, выделенная из исходного строкового значения по заданным правилам: с начала, с конца, из середины или по позиции найденного фрагмента. Сама по себе подстрока не является отдельным типом данных — это результат работы строковых функций встроенного языка: Лев, Прав, Сред, а также СтрНайти для определения позиции вхождения.

На практике выделение подстрок требуется постоянно: разобрать артикул на префикс и номер, извлечь код из наименования номенклатуры, отрезать лишние символы при загрузке данных из Excel или CSV, сформировать сокращённое представление документа. Почти любая обработка по обмену данными так или иначе использует эти функции.

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

Какие функции извлекают подстроку

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

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

ФункцияЧто возвращаетТипичный сценарий
Лев(Строка, N)Первые N символовПрефикс номера документа
Прав(Строка, N)Последние N символовКод из конца артикула
Сред(Строка, Поз, N)N символов с позиции ПозФрагмент между разделителями
СтрНайти(Строка, Подстр)Позицию вхождения или 0Поиск разделителя
СтрДлина(Строка)Длину строкиВычисление границ вырезки

Синтаксис и примеры кода

Рассмотрим базовые приёмы на конкретных примерах. Пусть есть артикул вида «ТОВ-001234-RU», и нужно извлечь его части:

Артикул = "ТОВ-001234-RU";

Префикс = Лев(Артикул, 3); // "ТОВ"

Суффикс = Прав(Артикул, 2); // "RU"

НомерЧасть = Сред(Артикул, 5, 6); // "001234"

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

Если запрошенная длина в Лев или Прав больше длины строки, функция просто вернёт всю строку целиком — ошибки не будет. Это удобно, но иногда маскирует логические ошибки: вы ожидаете строку из 10 символов, а получаете из 3, и дальше по коду это всплывёт в неожиданном месте.

bsl
Артикул = "ТОВ-001234-RU";
ПозицияДефиса = СтрНайти(Артикул, "-");
Если ПозицияДефиса > 0 Тогда
    Префикс = Лев(Артикул, ПозицияДефиса - 1);
КонецЕсли;

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

На практике позиции подстрок редко известны заранее — чаще они определяются через разделитель: дефис, запятую, пробел. Типовой приём — найти позицию разделителя функцией СтрНайти и от неё вычислить границы вырезки.

Строка = "Иванов Иван Иванович";

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

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

Фамилия = Лев(Строка, ПозицияПробела - 1); // "Иванов"

Остаток = Сред(Строка, ПозицияПробела + 1); // "Иван Иванович"

КонецЕсли;

Ключевой момент — проверка ПозицияПробела > 0. Если разделитель не найден, СтрНайти вернёт 0, и без проверки вы получите некорректные вырезки: Лев(Строка, -1) вызовет ошибку, а Сред(Строка, 1) вернёт всю строку, что может быть не тем, что вы ожидали.

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

Разбор строки на массив подстрок

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

СтрокаCSV = "Мука;Сахар;Соль";

Массив = СтрРазделить(СтрокаCSV, ";");

// Массив[0] = "Мука", Массив[1] = "Сахар", Массив[2] = "Соль"

Обратная операция — СтрСоединить(Массив, Разделитель) — склеивает массив подстрок обратно в одну строку. Эта пара функций покрывает большинство задач по разбору и сборке составных строк: путей к файлам, списков значений, служебных маркеров.

Учтите, что СтрРазделить по умолчанию включает пустые подстроки: при разборе «а;;б» вы получите три элемента, средний — пустой. Если пустые значения не нужны, передайте вторым параметром Ложь.

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

Типичные ошибки при работе с подстроками

Самая частая ошибка — забыть, что нумерация символов начинается с 1. Разработчик, привыкший к нулевой индексации, пишет Сред(Строка, 0, 5) и получает либо ошибку, либо сдвиг на один символ, который потом долго ищется в отладке.

Вторая группа ошибок связана с пробелами и невидимыми символами. Строки, загруженные из файлов или скопированные из внешних систем, часто содержат пробелы по краям и неразрывные пробелы внутри. Сравнение подстроки «АРТ» с реальным фрагментом « АРТ» даст ложь, хотя визуально всё выглядит одинаково. Перед разбором применяйте СокрЛП, а при подозрении на неразрывные пробелы — замену через СтрЗаменить с символом с кодом 160.

Третья типичная проблема — регистр. СтрНайти чувствительна к регистру: «арт» в строке «АРТ-123» не найдётся. Если регистр данных не гарантирован, приводите обе строки к одному регистру через ВРег или НРег перед поиском.

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

Производительность и ограничения

Строковые функции в 1С работают быстро на обычных данных, но в циклах по большим объёмам — сотни тысяч строк при загрузке прайсов или выгрузке отчётов — стоит помнить о нескольких моментах. Каждая операция создаёт новую строку в памяти, поэтому многократная склейка через Строка = Строка + Кусок в цикле работает медленнее, чем сборка через массив с последующим СтрСоединить.

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

Отдельное ограничение — строки неограниченной длины в запросах. Если вы работаете с подстрокой внутри запроса (функция ПОДСТРОКА языка запросов), помните, что сравнение и соединение по неограниченным строкам невозможны — сначала их нужно привести к фиксированной длине через ВЫРАЗИТЬ.

Сравнение подходов

Лев/Прав/Сред

Подходят, когда позиции известны или вычисляются просто. Ограничение — нужно вручную контролировать границы

СтрНайти + вырезка

Универсальный способ для строк с разделителем. Требует обязательной проверки, что разделитель найден

СтрРазделить

Лучший выбор для множества однотипных частей (CSV, списки). Не подходит, если разделитель может быть внутри данных

Регулярные выражения

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

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

После написания кода разбора строки проверьте его на граничных случаях: пустая строка, строка без разделителя, строка, начинающаяся или заканчивающаяся разделителем, строка из одного разделителя. Именно на таких данных всплывают ошибки, которые на «нормальных» значениях не видны.

Быстрый способ проверки — сообщить результат через Сообщить() с визуальными маркерами границ, например вывести подстроку в квадратных скобках: [АРТ]. Так сразу видно лишние пробелы и пустые значения, которые при обычном выводе незаметны.

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

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

Позиция разделителя
Норма

СтрНайти вернула число больше 0

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

Вернулся 0 — разделителя нет, вырезка некорректна

Границы подстроки
Норма

Вывод в скобках [значение] без пробелов по краям

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

Видны пробелы или пустые скобки — нужна СокрЛП или проверка данных

Количество частей
Норма

Массив после СтрРазделить содержит ожидаемое число элементов

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

Элементов меньше — обращение по индексу вызовет ошибку

Регистр при поиске
Норма

Обе строки приведены к одному регистру перед СтрНайти

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

Поиск не находит заведомо существующий фрагмент

Частые вопросы о подстроках в 1С

Чем подстрока отличается от строки в 1С?

Ничем на уровне типа данных: подстрока — это обычное значение типа «Строка», просто полученное как часть другой строки. Отдельного типа «подстрока» в платформе нет, термин описывает только происхождение значения.

Как удалить из строки найденную подстроку?

Проще всего функцией СтрЗаменить: СтрЗаменить(ИсходнаяСтрока, УдаляемыйФрагмент, "") вернёт строку без указанного фрагмента. Заменяются все вхождения, поэтому если нужно удалить только первое — сначала найдите его позицию через СтрНайти и соберите результат из Лев и Сред.

Что вернёт СтрНайти, если подстрока не найдена?

Ноль. Это значение обязательно нужно проверять перед использованием позиции в Лев, Прав или Сред, иначе получите либо ошибку выполнения, либо некорректный результат, который трудно отловить.

Как получить подстроку в запросе 1С?

В языке запросов есть функция ПОДСТРОКА(Поле, НачальнаяПозиция, Длина) — аналог Сред. Учтите, что для полей неограниченной длины её применение и последующие соединения ограничены: сначала приведите поле к фиксированной длине через ВЫРАЗИТЬ(Поле КАК Строка(N)).

Чувствителен ли поиск подстроки к регистру?

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

Как разбить строку с разными разделителями?

Функция СтрРазделить принимает строку из нескольких символов-разделителей: СтрРазделить(Текст, ";,") разрежет и по точке с запятой, и по запятой. Если нужен разделитель из нескольких символов как единое целое, придётся использовать СтрНайти в цикле.

Итог

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

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