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

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

Как разбить строку на подстроки в 1С

Как разбить строку на подстроки в 1С: функция СтрРазделить, работа с разделителями, разбор CSV, многострочного текста и типичные ошибки с примерами кода.

Разбиение строки на подстроки — одна из самых частых задач при обработке данных в 1С: разбор ФИО на фамилию, имя и отчество, чтение CSV-файлов, разбор адресов, артикулов, значений из внешних систем. Во встроенном языке 1С для этого есть штатная функция СтрРазделить, а также более старые приёмы через СтрЗаменить и перебор вхождений разделителя, которые до сих пор встречаются в типовых конфигурациях и внешних обработках.

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

Функция СтрРазделить — основной способ

Функция СтрРазделить принимает три параметра: исходную строку, строку-разделитель и необязательный булев параметр «ВключатьПустые». Результат — массив, каждый элемент которого является подстрокой между разделителями. Сам разделитель в результат не входит.

СтрокаАдреса = "г. Москва, ул. Ленина, д. 10, кв. 5";

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

// Части[0] = "г. Москва"

// Части[1] = " ул. Ленина"

// Части[2] = " д. 10"

// Части[3] = " кв. 5"

Обратите внимание: после запятой в строке стоят пробелы, поэтому элементы массива начинаются с пробела. Если разделитель указать как ", " (запятая с пробелом), пробелы исчезнут. Либо дополнительно обработайте каждый элемент функцией СокрЛП, которая убирает незначащие пробелы по краям.

Разделителем может быть строка любой длины — не обязательно один символ. Например, для разбора пути вида «Справочник.Номенклатура/Группа/Элемент» удобно указать разделитель "/", а для строки с составным разделителем вроде « -- » — всю последовательность целиком.

1c
Массив = СтрРазделить("Иванов;Петров;Сидоров", ";", Ложь);
Для Каждого Элемент Из Массив Цикл
    Сообщить(СокрЛП(Элемент));
КонецЦикла;

Параметр «ВключатьПустые» и потеря пустых значений

Третий параметр функции определяет, попадут ли в массив пустые подстроки — участки между двумя идущими подряд разделителями. По умолчанию он равен Истина, и пустые элементы сохраняются. Это критично при разборе позиционных форматов, где порядок полей фиксирован.

Рассмотрим строку "Иванов;;Сергеевич". Если вызвать СтрРазделить(Строка, ";", Истина), получим массив из трёх элементов, где второй — пустая строка. Если передать Ложь, массив сократится до двух элементов, и «Сергеевич» окажется на месте отчества — ошибка, которую сложно заметить сразу, но она испортит данные в справочнике.

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

Разбор многострочного текста по строкам

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

Первый — разделить по символу перевода строки через СтрРазделить:

Строки = СтрРазделить(Текст, Символы.ПС);

Для Каждого Стр Из Строки Цикл

// обработка строки

КонецЦикла;

Второй — классическая связка СтрЧислоСтрок и СтрПолучитьСтроку. Она работает на любых версиях платформы, включая очень старые, и корректно обрабатывает разные варианты переводов строк (CR, LF, CRLF), что особенно важно при чтении файлов, созданных в разных операционных системах.

КоличествоСтрок = СтрЧислоСтрок(Текст);

Для НомерСтроки = 1 По КоличествоСтрок Цикл

ТекущаяСтрока = СтрПолучитьСтроку(Текст, НомерСтроки);

// обработка строки

КонецЦикла;

Разбор CSV и строк с кавычками

Наивный разбор CSV-строки простым СтрРазделить(Строка, ";") ломается, как только внутри значения появляется разделитель, экранированный кавычками: "ООО ""Ромашка"";Москва;100". Точка с запятой внутри кавычек — часть значения, а не разделитель полей.

Если в данных гарантированно нет кавычек и вложенных разделителей (например, выгрузка под вашим контролем), простого разбиения достаточно. Если файл приходит из внешней системы и формат полноценный CSV, потребуется посимвольный разбор: идти по строке, отслеживать состояние «внутри кавычек» и разбивать только по разделителям вне кавычек.

Упрощённая логика такого разбора выглядит следующим образом: перебираете символы, при встрече кавычки переключаете флаг, при встрече разделителя вне кавычек — фиксируете очередное поле. Двойные кавычки внутри значения ("") заменяются на одну. Такой код длиннее, но единственно корректен для произвольного CSV.

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

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

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

Способы для старых версий платформы

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

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

Подготовленная = СтрЗаменить(Строка, ";", Символы.ПС);

Для Н = 1 По СтрЧислоСтрок(Подготовленная) Цикл

Элемент = СтрПолучитьСтроку(Подготовленная, Н);

КонецЦикла;

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

Остаток = Строка;

Пока Истина Цикл

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

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

Элемент = Остаток; // последний элемент

// обработка

Прервать;

КонецЕсли;

Элемент = Лев(Остаток, Позиция - 1);

Остаток = Сред(Остаток, Позиция + 1);

// обработка

КонецЦикла;

Проверка результата и обработка крайних случаев

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

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

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

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

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

Совпадает с числом полей в формате

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

Меньше или больше ожидаемого — строка битая или формат изменился

Значения элементов
Норма

Нет лишних пробелов и символов ВК по краям

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

Пробелы, CR в конце — нужна обработка СокрЛП

Пустые элементы на позиционных местах
Норма

Пустые поля сохранены на своих позициях

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

Поля съехали — проверьте параметр ВключатьПустые

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

Типичные ошибки
01
Не указывать третий параметр СтрРазделить осознанно — по умолчанию Истина, и при разборе пользовательского ввода в массив попадают пустые строки, которые потом создают пустые записи в таблицах
02
Искать элементы по индексу без проверки количества — обращение к Массив[2] при двух элементах вызывает ошибку выполнения и обрыв обработки
03
Разбивать CSV простым СтрРазделить по запятой — значения с разделителем внутри кавычек разваливаются на несколько полей
04
Забывать про последний элемент в цикле с Найти() и Сред() — после последнего разделителя остаётся хвост строки, который нужно обработать отдельно
05
Разбивать по Символы.ПС текст из файла с переводами CRLF — в конце каждой строки остаётся Символы.ВК, который ломает сравнения и поиск

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

Итог

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

Основной инструмент — СтрРазделить с явно заданным параметром ВключатьПустые. Многострочный текст надёжнее перебирать через СтрПолучитьСтроку. CSV с кавычками требует посимвольного разбора. Всегда проверяйте количество элементов и очищайте значения через СокрЛП перед записью в базу.

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

Чем СтрРазделить отличается от СтрПолучитьСтроку?

СтрРазделить разбивает строку по произвольному разделителю и возвращает массив. СтрПолучитьСтроку работает только с многострочным текстом и возвращает строку по её номеру, при этом корректно обрабатывает разные типы переводов строк. Для разбора файлов построчно обычно удобнее вторая, для разбора полей внутри строки — первая.

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

Штатной функции с несколькими разделителями в языке нет. Практичный приём — предварительно заменить все дополнительные разделители на один основной через СтрЗаменить, а затем вызвать СтрРазделить. Например, заменить запятые и точки с запятой на один символ-разделитель и разбить по нему.

Почему после разбора в элементах появляются лишние пробелы?

СтрРазделить не удаляет пробелы — она делит строку строго по разделителю. Если в исходных данных после разделителя стоит пробел, он останется в начале элемента. Решение — включать пробел в разделитель или применять СокрЛП к каждому элементу массива перед использованием.

Что вернёт СтрРазделить, если разделителя в строке нет?

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

Как разбить строку на части фиксированной длины, а не по разделителю?

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

Есть ли ограничения по длине строки при разбиении?

Жёсткого практического лимита на длину строки во встроенном языке для таких операций нет, ограничение упирается в доступную память. Однако при разборе очень больших текстов (сотни мегабайт) эффективнее читать данные порциями через ЧтениеТекста или ТекстовыйДокумент, чем загружать весь текст в одну строковую переменную и разбивать целиком.