Разработка и Конфигурация · 11 мин
Как разбить строку на подстроки в 1С
Как разбить строку на подстроки в 1С: функция СтрРазделить, работа с разделителями, разбор CSV, многострочного текста и типичные ошибки с примерами кода.
Разбиение строки на подстроки — одна из самых частых задач при обработке данных в 1С: разбор ФИО на фамилию, имя и отчество, чтение CSV-файлов, разбор адресов, артикулов, значений из внешних систем. Во встроенном языке 1С для этого есть штатная функция СтрРазделить, а также более старые приёмы через СтрЗаменить и перебор вхождений разделителя, которые до сих пор встречаются в типовых конфигурациях и внешних обработках.
Выбор способа зависит от версии платформы, структуры исходной строки и того, нужно ли сохранять пустые элементы. Ниже разобраны основные варианты с примерами кода, ограничения каждого подхода и типичные ошибки, которые приводят к потере данных при разборе.
Функция СтрРазделить — основной способ
Функция СтрРазделить принимает три параметра: исходную строку, строку-разделитель и необязательный булев параметр «ВключатьПустые». Результат — массив, каждый элемент которого является подстрокой между разделителями. Сам разделитель в результат не входит.
СтрокаАдреса = "г. Москва, ул. Ленина, д. 10, кв. 5";
Части = СтрРазделить(СтрокаАдреса, ",");
// Части[0] = "г. Москва"
// Части[1] = " ул. Ленина"
// Части[2] = " д. 10"
// Части[3] = " кв. 5"
Обратите внимание: после запятой в строке стоят пробелы, поэтому элементы массива начинаются с пробела. Если разделитель указать как ", " (запятая с пробелом), пробелы исчезнут. Либо дополнительно обработайте каждый элемент функцией СокрЛП, которая убирает незначащие пробелы по краям.
Разделителем может быть строка любой длины — не обязательно один символ. Например, для разбора пути вида «Справочник.Номенклатура/Группа/Элемент» удобно указать разделитель "/", а для строки с составным разделителем вроде « -- » — всю последовательность целиком.
Массив = СтрРазделить("Иванов;Петров;Сидоров", ";", Ложь);
Для Каждого Элемент Из Массив Цикл
Сообщить(СокрЛП(Элемент));
КонецЦикла;Параметр «ВключатьПустые» и потеря пустых значений
Третий параметр функции определяет, попадут ли в массив пустые подстроки — участки между двумя идущими подряд разделителями. По умолчанию он равен Истина, и пустые элементы сохраняются. Это критично при разборе позиционных форматов, где порядок полей фиксирован.
Рассмотрим строку "Иванов;;Сергеевич". Если вызвать СтрРазделить(Строка, ";", Истина), получим массив из трёх элементов, где второй — пустая строка. Если передать Ложь, массив сократится до двух элементов, и «Сергеевич» окажется на месте отчества — ошибка, которую сложно заметить сразу, но она испортит данные в справочнике.
Обратная ситуация — разбор пользовательского ввода, где лишние разделители означают мусор. Например, при разборе списка артикулов, введённых через запятую, пустые элементы лучше отбросить, передав Ложь, чтобы не создавать пустые строки в табличной части.
Разбор многострочного текста по строкам
Частая задача — разбить многострочный текст (например, содержимое текстового файла или многострочного поля) на отдельные строки. Здесь есть два рабочих подхода, и они не взаимозаменяемы в общем случае.
Первый — разделить по символу перевода строки через СтрРазделить:
Строки = СтрРазделить(Текст, Символы.ПС);
Для Каждого Стр Из Строки Цикл
// обработка строки
КонецЦикла;
Второй — классическая связка СтрЧислоСтрок и СтрПолучитьСтроку. Она работает на любых версиях платформы, включая очень старые, и корректно обрабатывает разные варианты переводов строк (CR, LF, CRLF), что особенно важно при чтении файлов, созданных в разных операционных системах.
КоличествоСтрок = СтрЧислоСтрок(Текст);
Для НомерСтроки = 1 По КоличествоСтрок Цикл
ТекущаяСтрока = СтрПолучитьСтроку(Текст, НомерСтроки);
// обработка строки
КонецЦикла;
Разбор CSV и строк с кавычками
Наивный разбор CSV-строки простым СтрРазделить(Строка, ";") ломается, как только внутри значения появляется разделитель, экранированный кавычками: "ООО ""Ромашка"";Москва;100". Точка с запятой внутри кавычек — часть значения, а не разделитель полей.
Если в данных гарантированно нет кавычек и вложенных разделителей (например, выгрузка под вашим контролем), простого разбиения достаточно. Если файл приходит из внешней системы и формат полноценный CSV, потребуется посимвольный разбор: идти по строке, отслеживать состояние «внутри кавычек» и разбивать только по разделителям вне кавычек.
Упрощённая логика такого разбора выглядит следующим образом: перебираете символы, при встрече кавычки переключаете флаг, при встрече разделителя вне кавычек — фиксируете очередное поле. Двойные кавычки внутри значения ("") заменяются на одну. Такой код длиннее, но единственно корректен для произвольного CSV.
Как выбрать способ разбора
Способы для старых версий платформы
Функция СтрРазделить появилась не сразу, и в конфигурациях на старых версиях платформы её может не быть. Там применяются два классических приёма, которые до сих пор встречаются в типовом коде.
Первый — замена разделителя на перевод строки с последующим перебором. Приём работает, только если в исходной строке гарантированно нет переводов строк, иначе результат исказится:
Подготовленная = СтрЗаменить(Строка, ";", Символы.ПС);
Для Н = 1 По СтрЧислоСтрок(Подготовленная) Цикл
Элемент = СтрПолучитьСтроку(Подготовленная, Н);
КонецЦикла;
Второй — цикл с поиском позиции разделителя функцией Найти и вырезанием подстроки через Лев и Сред. Этот вариант универсальнее: он не чувствителен к переводам строк, но требует аккуратной обработки последнего элемента после цикла — именно его чаще всего теряют.
Остаток = Строка;
Пока Истина Цикл
Позиция = Найти(Остаток, ";");
Если Позиция = 0 Тогда
Элемент = Остаток; // последний элемент
// обработка
Прервать;
КонецЕсли;
Элемент = Лев(Остаток, Позиция - 1);
Остаток = Сред(Остаток, Позиция + 1);
// обработка
КонецЦикла;
Проверка результата и обработка крайних случаев
После разбиения не полагайтесь на ожидаемое количество элементов — проверяйте его явно. Строка из внешнего источника может быть пустой, содержать только разделители или обрываться посередине. Минимальная защита — сравнить Массив.Количество() с ожидаемым числом полей и при несовпадении записать ошибку в журнал, а не молча продолжать.
Отдельные крайние случаи: пустая исходная строка (результат — массив из одного пустого элемента, а не пустой массив), разделитель в начале или конце строки (даёт пустые элементы по краям при ВключатьПустые = Истина), разделитель, которого нет в строке (массив из одного элемента — самой строки). Все три ситуации — не ошибка выполнения, поэтому исключения не возникнет, и проблему можно заметить только проверкой.
Как проверить результат разбора
Совпадает с числом полей в формате
Меньше или больше ожидаемого — строка битая или формат изменился
Нет лишних пробелов и символов ВК по краям
Пробелы, CR в конце — нужна обработка СокрЛП
Пустые поля сохранены на своих позициях
Поля съехали — проверьте параметр ВключатьПустые
Типичные ошибки при разбиении строк
Ещё одна распространённая проблема — производительность при разборе больших файлов. Если вы разбираете строку внутри цикла по тысячам строк файла, убедитесь, что не выполняете лишних операций: выносите неизменные вычисления из цикла, а при работе с большими текстами рассмотрите ТекстовыйДокумент с построчным чтением вместо загрузки всего файла в память одной строкой.
Что важно запомнить
Основной инструмент — СтрРазделить с явно заданным параметром ВключатьПустые. Многострочный текст надёжнее перебирать через СтрПолучитьСтроку. CSV с кавычками требует посимвольного разбора. Всегда проверяйте количество элементов и очищайте значения через СокрЛП перед записью в базу.
Частые вопросы
Чем СтрРазделить отличается от СтрПолучитьСтроку?
СтрРазделить разбивает строку по произвольному разделителю и возвращает массив. СтрПолучитьСтроку работает только с многострочным текстом и возвращает строку по её номеру, при этом корректно обрабатывает разные типы переводов строк. Для разбора файлов построчно обычно удобнее вторая, для разбора полей внутри строки — первая.
Как разбить строку по нескольким разным разделителям сразу?
Штатной функции с несколькими разделителями в языке нет. Практичный приём — предварительно заменить все дополнительные разделители на один основной через СтрЗаменить, а затем вызвать СтрРазделить. Например, заменить запятые и точки с запятой на один символ-разделитель и разбить по нему.
Почему после разбора в элементах появляются лишние пробелы?
СтрРазделить не удаляет пробелы — она делит строку строго по разделителю. Если в исходных данных после разделителя стоит пробел, он останется в начале элемента. Решение — включать пробел в разделитель или применять СокрЛП к каждому элементу массива перед использованием.
Что вернёт СтрРазделить, если разделителя в строке нет?
Массив из одного элемента, содержащего исходную строку целиком. Ошибки не возникнет. Поэтому, если наличие разделителя — признак корректного формата, проверяйте количество элементов: один элемент при ожидаемых нескольких означает, что строка не соответствует формату.
Как разбить строку на части фиксированной длины, а не по разделителю?
СтрРазделить здесь не подходит — используйте цикл с функцией Сред(Строка, Позиция, Длина), сдвигая позицию на фиксированный шаг. Не забудьте обработать последний фрагмент: если длина строки не кратна шагу, хвост будет короче, и Сред корректно вернёт оставшиеся символы без ошибки.
Есть ли ограничения по длине строки при разбиении?
Жёсткого практического лимита на длину строки во встроенном языке для таких операций нет, ограничение упирается в доступную память. Однако при разборе очень больших текстов (сотни мегабайт) эффективнее читать данные порциями через ЧтениеТекста или ТекстовыйДокумент, чем загружать весь текст в одну строковую переменную и разбивать целиком.