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

В этой статье разберём 5 рабочих способов разделения строк прямо в SQL-запросах 1С 8.3, включая обходные пути для старых версий платформы, обработку многобайтовых кодировок (например, UTF-8) и нюансы работы с большими текстами. Особое внимание уделим разделению строк с учетом экранированных символов — это частая причина ошибок при импорте данных из внешних источников.

1. Стандартные функции 1С для разделения строк

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

  • 🔹 СтрРазделить(Строка, Разделитель) — возвращает массив строк, разделённых указанным символом (или подстрокой). Работает только во встроенном языке, но не в SQL-запросах.
  • 🔹 СтрЧислоВхождений(Подстрока, Строка) — помогает посчитать количество разделителей перед разбором.
  • 🔹 Лев(Строка, Длина) / Прав(Строка, Длина) — для извлечения частей строки по фиксированной длине.
  • 🔹 СтрЗаменить(Строка, Старое, Новое) — полезно для предварительной очистки данных (например, замены двойных пробелов).

Пример использования СтрРазделить() во встроенном языке:

МассивСтрок = СтрРазделить("яблоко,банан,груша", ",");

Для Каждого Элемент Из МассивСтрок Цикл

Сообщить(Элемент);

КонецЦикла;

⚠️ Внимание: В SQL-запросах эти функции недоступны! Их можно использовать только в коде модулей или при пост-обработке результатов запроса.

Если вам нужно разделить строку прямо в запросе, придётся использовать другие подходы — о них поговорим далее.

2. Разделение строк в SQL-запросах 1С: обходные пути

В отличие от встроенного языка, язык запросов 1С не имеет специализированных функций для работы со строками. Однако есть несколько трюков:

  • 🔧 Использование ПОДСТРОКА — для извлечения частей строки по позициям. Например, чтобы получить первые 5 символов: ЛЕВ(Поле, 5).
  • 🔧 Поиск позиций разделителя через НАЙТИ или ПОЗИЦИЯ, а затем обрезка строки.
  • 🔧 Рекурсивные запросы (для сложных случаев) — позволяют разбирать строки с вложенными разделителями.

Пример запроса, который извлекает первую часть строки до запятой:

ВЫБРАТЬ

ЛЕВ(ТекстовоеПоле, НАЙТИ(ТекстовоеПоле, ",") - 1) КАК ПерваяЧасть

ИЗ

Документ.МойДокумент

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

📊 Какой метод разделения строк вы используете чаще?
Встроенные функции 1С
SQL-запросы с ПОДСТРОКА
Регулярные выражения
Собственные алгоритмы

3. Регулярные выражения для сложных разделителей

Когда строка имеет нестандартный формат (например, данные в кавычках, экранированные символы или несколько разделителей подряд), на помощь приходят регулярные выражения. В 1С 8.3.10+ они поддерживаются через объект РегулярноеВыражение.

Пример разбора строки с регулярками:

РегВыр = Новый РегулярноеВыражение("""([^""])""\s,\s*""([^""]*)""");

Результат = РегВыр.ВыполнитьПоиск('"Иванов";"Петр";"Сергеевич"');

Если Результат.Найдено Тогда

Сообщить(Результат.Группа(1)); // Иванов

Сообщить(Результат.Группа(2)); // Петр

КонецЕсли;

Для использования регулярных выражений внутри запроса придётся создать виртуальную таблицу или использовать ВЫРАЗИТЬ с предварительной обработкой.

⚠️ Внимание: Регулярные выражения в 1С работают медленнее встроенных функций. Не используйте их для обработки больших объёмов данных (свыше 10 000 строк) без оптимизации.
💡

Если вам нужно разделить строку по нескольким разделителям (например, запятая или точка с запятой), используйте регулярное выражение с группой символов: [,;]

4. Разделение строк с учетом экранированных символов

Одна из самых сложных задач — разбор строк, где разделители могут быть экранированы (например, CSV-файлы с полями в кавычках). Типичный пример:

"Иванов, Иван""Иванович";"Москва; ул. Ленина, д.1"

Здесь запятые и точки с запятой внутри кавычек не должны считаться разделителями. Для такого случая алгоритм будет следующим:

  1. Пройти по строке символ за символом.
  2. Отслеживать, находимся ли мы внутри кавычек (флаг ВнутриКавычек).
  3. Разделять строку только по неэкранированным разделителям.

Пример кода для обработки такого случая:

Функция РазделитьСЭкранированием(Строка, Разделитель)

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

ТекущаяЧасть = "";

ВнутриКавычек = Ложь;

Для Инд = 1 По СтрДлина(Строка) Цикл

Символ = Сред(Строка, Инд, 1);

Если Символ = """" Тогда

ВнутриКавычек = Не ВнутриКавычек;

ИначеЕсли Символ = Разделитель И Не ВнутриКавычек Тогда

Результат.Добавить(ТекущаяЧасть);

ТекущаяЧасть = "";

Продолжить;

КонецЕсли;

ТекущаяЧасть = ТекущаяЧасть + Символ;

КонецЦикла;

Если ТекущаяЧасть <> "" Тогда

Результат.Добавить(ТекущаяЧасть);

КонецЕсли;

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

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

Что будет, если не учитывать экранирование?

Без обработки кавычек строка '"Иванов, Иван""Иванович";"Москва"' разобьётся на 4 части вместо двух:

  1. "Иванов
  2. Иван"Иванович"
  3. "Москва"
  4. пустая строка

5. Разделение строк в больших данных: оптимизация производительности

При работе с большими объёмами данных (например, импорт CSV-файла на 100 000 строк) стандартные методы могут тормозить. В таких случаях:

  • 🚀 Используйте пакетную обработку — разбивайте данные на порции по 1 000–5 000 строк.
  • 🚀 Отключайте транзакционность на время массовой загрузки (если это допустимо).
  • 🚀 Применяйте временные таблицы для промежуточных результатов.
  • 🚀 Для CSV используйте специализированные обработки (например, ЧтениеCSV из библиотеки OneScript).

Пример оптимизированного кода для пакетного разделения:

Процедура ОбработатьБольшойФайл(ПутьКФайлу)

Текст = Новый ЧтениеТекста(ПутьКФайлу);

Пачка = Новый Массив;

Счетчик = 0;

Пока Текст.ПрочитатьСтроку() Цикл

Пачка.Добавить(РазделитьСтроку(Текст.ТекущаяСтрока));

Счетчик = Счетчик + 1;

Если Счетчик >= 1000 Тогда

ЗаписатьПачкуВБазу(Пачка);

Пачка.Очистить();

Счетчик = 0;

КонецЕсли;

КонецЦикла;

Если Пачка.Количество() > 0 Тогда

ЗаписатьПачкуВБазу(Пачка);

КонецЕсли;

КонецПроцедуры;

Метод Скорость Сложность реализации Подходит для больших данных
СтрРазделить() Средняя Низкая Нет
SQL-запросы с ПОДСТРОКА Высокая Средняя Да (с ограничениями)
Регулярные выражения Низкая Высокая Нет
Пакетная обработка Очень высокая Высокая Да

6. Типичные ошибки и как их избежать

Даже опытные разработчики иногда сталкиваются с проблемами при разделении строк. Вот самые распространённые ошибки:

  • Игнорирование пустых элементов — если строка заканчивается разделителем (например, "a,b,c,"), последний элемент может потеряться.
  • Неучёт многобайтовых символов — функции вроде Сред() работают с байтами, а не с символами в UTF-8.
  • Переполнение памяти при обработке очень длинных строк (свыше 10 МБ).
  • Неправильная обработка переносов строк (например, \r\n vs \n).

Чтобы избежать этих проблем:

⚠️ Внимание: Всегда проверяйте результат разделения на крайние случаи: пустые строки, строки только с разделителями, строки с экранированными символами. Используйте модульные тесты!

☑️ Проверка корректности разделения строк

Выполнено: 0 / 4

7. Практический пример: разбор CSV в 1С

Рассмотрим полный пример загрузки CSV-файла с разделением строк и записью в справочник Номенклатура.

Исходный файл goods.csv:

"Артикул","Наименование","Цена"

"ART001","Стул офисный","1500.50"

"ART002","Стол письменный; большой","3200.00"

Код обработки:

Процедура ЗагрузитьCSV(ПутьКФайлу)

// 1. Чтение файла

Текст = Новый ЧтениеТекста(ПутьКФайлу);

Разделитель = ",";

// 2. Пропускаем заголовок

Текст.ПрочитатьСтроку();

// 3. Обрабатываем строки

Пока Текст.ПрочитатьСтроку() Цикл

Данные = РазделитьСЭкранированием(Текст.ТекущаяСтрока, Разделитель);

НоваяНоменклатура = Справочники.Номенклатура.СоздатьЭлемент();

НоваяНоменклатура.Артикул = Данные[0];

НоваяНоменклатура.Наименование = Данные[1];

НоваяНоменклатура.Цена = Число(Данные[2]);

НоваяНоменклатура.Записать();

КонецЦикла;

КонецПроцедуры;

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

💡

Для CSV-файлов всегда проверяйте первую строку на наличие заголовков и кодировку (ANSI/UTF-8). В 1С для чтения UTF-8 используйте ЧтениеТекста с параметром КодировкаТекста.UTF8.

FAQ: Частые вопросы по разделению строк в 1С

Можно ли разделить строку прямо в запросе 1С без пост-обработки?

В чистом SQL-запросе нет встроенных функций для разделения строк на массивы. Однако можно:

  • Использовать ПОДСТРОКА для извлечения первой/последней части.
  • Создать виртуальную таблицу с предварительно разделёнными данными.
  • Применить рекурсивный запрос (для простых случаев).

Для сложных сценариев лучше разделять строки во встроенном языке после выполнения запроса.

Как разделить строку по нескольким разделителям (например, запятая или точка с запятой)?

Есть два подхода:

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

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

  2. Регулярное выражение:
    РегВыр = Новый РегулярноеВыражение("[,;]");
    

    Результат = РегВыр.Разбить("a,b;c,d");

Почему функция СтрРазделить() неправильно работает с кириллицей?

Проблема возникает из-за неверной кодировки исходной строки. Например, если строка в UTF-8, а 1С ожидает ANSI, символы кириллицы могут "разбиваться" на несколько байт, что приводит к ошибкам при разделении.

Решение:

// Преобразуем строку в UTF-8 перед разделением

Текст = СтрокаДляUTF8(ИсходнаяСтрока);

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

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

Используйте комбинацию функций ЛЕВ(), ПРАВ() и СРЕД(). Пример для разделения на части по 10 символов:

Для Инд = 1 По СтрДлина(Строка) / 10 Цикл

Часть = Сред(Строка, (Инд - 1) * 10 + 1, 10);

Сообщить(Часть);

КонецЦикла;

Для последней части проверьте остаток от деления длины строки на 10.

Можно ли использовать Split() как в других языках программирования?

В 1С нет прямого аналога Split() из JavaScript или Python, но функциональность полностью покрывается:

  • СтрРазделить() — для простых случаев.
  • РегулярноеВыражение.Разбить() — для сложных шаблонов.
  • Кастомные функции — для специфических задач (например, с экранированием).