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

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

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

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

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

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

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

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

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

СтрокаДанных = "Иванов;Пётр;Сидорович";

МассивЧастей = СтрРазделить(СтрокаДанных, ";");

// МассивЧастей[0] = "Иванов"

// МассивЧастей[1] = "Пётр"

// МассивЧастей[2] = "Сидорович"

Разделителем может быть строка любой длины, а не только один символ. Например, СтрРазделить(Текст, " - ") корректно разобьёт строку вида «Москва - Склад 1 - Резерв». Это удобно, когда данные содержат одиночные дефисы, которые разбивать не нужно.

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

Обработка пустых элементов

Третий параметр функции определяет, попадут ли в массив пустые подстроки. По умолчанию он равен Истина, то есть пустые элементы включаются. Строка «А;;Б» при разборе с разделителем «;» даст массив из трёх элементов: «А», «», «Б».

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

Ошибка возникает, когда код рассчитывает на фиксированное число элементов, а пустые отброшены. Если вы разбираете CSV-подобную строку с обязательными колонками, включение пустых обязательно — иначе сместятся индексы и данные попадут не в те поля. Например, в строке «Иванов;;Москва» отсутствует отчество, и при отбрасывании пустых «Москва» окажется на месте отчества.

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

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

МассивСтрок = Новый Массив;

Для Номер = 1 По СтрЧислоСтрок(Текст) Цикл

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

Если Не ПустаяСтрока(ТекущаяСтрока) Тогда

МассивСтрок.Добавить(ТекущаяСтрока);

КонецЕсли;

КонецЦикла;

Тот же результат можно получить через СтрРазделить(Текст, Символы.ПС), что короче. Однако есть нюанс: файлы, созданные в Windows, часто используют пару символов ВК+ПС (CRLF). Тогда после разбора по ПС в конце каждого элемента останется символ возврата каретки, который при сравнении строк даст ложное неравенство. Надёжнее предварительно выполнить СтрЗаменить(Текст, Символы.ВК, "").

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

Ручной разбор для старых платформ

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

Функция РазбитьСтроку(Знач Строка, Разделитель)

Результат = Новый Массив;

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

Пока Позиция > 0 Цикл

Результат.Добавить(Лев(Строка, Позиция - 1));

Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));

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

КонецЦикла;

Результат.Добавить(Строка);

Возврат Результат;

КонецФункции

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

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

Альтернативные инструменты разбора

Помимо прямого разбиения, в 1С есть объекты, которые решают смежные задачи. Выбор зависит от формата источника и того, что требуется на выходе.

  • ТекстовыйДокумент — читает файл построчно через ПолучитьСтроку(), подходит для больших файлов, которые неудобно загружать в память целиком;
  • ЧтениеТекста — потоковое чтение с методом ПрочитатьСтроку(), экономит память на больших файлах;
  • СписокЗначений — имеет метод ЗагрузитьЗначения(), принимающий массив, если нужен не массив, а именно список для интерфейса;
  • ЧтениеJSON / ЧтениеXML — если данные приходят в этих форматах, разбивать строку вручную не нужно вовсе, структура извлекается штатными средствами.

Для обратной операции — сборки массива обратно в строку — используется функция СтрСоединить(Массив, Разделитель). Пара «СтрРазделить / СтрСоединить» покрывает большинство сценариев сериализации списков в строку и обратно, например для хранения списка значений в строковом реквизите.

Сравнение вариантов

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

Универсальный способ для платформы 8.3.6 и новее; не подходит только для очень старых версий

СтрЧислоСтрок + СтрПолучитьСтроку

Удобно для многострочного текста и построчной обработки с фильтрацией; медленнее на больших текстах

Ручной цикл с Найти()

Единственный вариант для платформ ниже 8.3.6; требует аккуратной обработки последнего элемента

ЧтениеТекста / ТекстовыйДокумент

Для больших файлов, когда загружать всё в память нежелательно; требует работы с файлом, а не со строкой в памяти

Проверка результата и отладка

После разбора всегда проверяйте количество элементов перед обращением по индексу. Конструкция Если Массив.Количество() >= 3 Тогда ... КонецЕсли; спасёт от ошибки «Индекс находится за границами массива», когда во входных данных не хватает частей.

При отладке полезно вывести результат через Сообщить() в цикле или посмотреть массив в табло (Ctrl+Shift+F9 в конфигураторе). Обращайте внимание на непечатаемые символы: пробелы по краям, табуляции, возвраты каретки. Их видно, если обернуть элемент в квадратные скобки при выводе — лишние символы сразу проявятся.

Для очистки элементов от окружающих пробелов применяйте СокрЛП() к каждому элементу после разбора. Часто данные приходят в виде «значение1, значение2, значение3» с пробелами после запятых, и без сокращения сравнение с эталонными значениями будет давать ложь.

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

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

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

Совпадает с ожидаемым числом частей

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

Меньше ожидаемого — возможно, пустые элементы отброшены или разделитель не совпал

Первый и последний элементы
Норма

Содержат ожидаемые значения без лишних символов

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

Пустые или содержат невидимые символы — проверьте края строки и CRLF

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

Сравнение даёт Истина

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

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

Практический порядок действий

Типовой сценарий: получили строку из файла, формы или веб-сервиса и нужно разложить её в структуру данных. Соблюдайте последовательность, чтобы не отлаживать ошибки на боевых данных.

Порядок действий
  1. 1
    Определите точный разделитель: посмотрите реальные данные, а не предполагайте формат
  2. 2
    Проверьте версию платформы: если 8.3.6 и выше — используйте СтрРазделить
  3. 3
    Очистите строку от лишнего: уберите Символы.ВК при разборе многострочного текста
  4. 4
    Выполните разбор и проверьте Количество() элементов массива
  5. 5
    Примените СокрЛП к каждому элементу перед использованием
  6. 6
    Проверьте результат на тестовом примере с граничными случаями: пустая строка, строка без разделителя, завершающий разделитель

Отдельно протестируйте краевые случаи. Пустая строка на входе даёт массив из одного пустого элемента (при включённых пустых), а не пустой массив — это неочевидно и ломает логику проверок вида «если массив пустой». Строка без разделителя вернёт массив из одного элемента с исходной строкой. Строка, заканчивающаяся разделителем, даст последним элементом пустую строку.

При разборе CSV-файлов учитывайте, что значения могут содержать разделитель внутри кавычек. Простой СтрРазделить такой формат корректно не обработает — понадобится посимвольный разбор с отслеживанием открытых кавычек или готовая обработка загрузки табличных данных.
ПЗ
Практическое замечание

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

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

СтрРазделить работает с произвольным разделителем и сразу возвращает массив. СтрПолучитьСтроку извлекает одну строку из многострочного текста по её номеру и требует цикла вместе со СтрЧислоСтрок. Для разбора по запятой или точке с запятой подходит только первый вариант.

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

Передайте все символы-разделители одной строкой во втором параметре: СтрРазделить(Строка, ";,|"). Каждый символ будет трактоваться как разделитель. Если разделители многосимвольные и разные, сначала замените их на один унифицированный через СтрЗаменить, затем выполните разбор.

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

Чаще всего виноваты невидимые символы: пробелы по краям, табуляция или возврат каретки (Символы.ВК), оставшийся от Windows-переносов строк. Примените СокрЛП к каждому элементу и предварительно удалите ВК из исходного текста через СтрЗаменить.

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

Массив из одного элемента с пустой строкой, если включение пустых не отключено. Поэтому проверка «Массив.Количество() = 0» не сработает — проверяйте входную строку функцией ПустаяСтрока() до разбора.

Как собрать массив обратно в строку?

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

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

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

Итог

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

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