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