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

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

Строка как массив в 1С: обход символов и разбор строк

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

В языке 1С нет прямого обращения к символу строки по индексу, как в C# или Python: конструкция Строка[0] вызовет ошибку. Тем не менее строку вполне можно обрабатывать как массив — для этого используются встроенные функции СтрДлина, Сред, Лев, Прав, а также СтрРазделить и СтрСоединить, которые преобразуют строку в настоящий массив подстрок и обратно.

Задача «пройтись по строке как по массиву» возникает постоянно: проверка ИНН посимвольно, разбор артикула по позициям, поиск недопустимых символов в наименовании, парсинг строк из обменных файлов. У каждого подхода — свои ограничения по производительности и читаемости, и выбирать их стоит осознанно.

В этом материале разобраны все рабочие способы: цикл по символам через Сред, разделение строки в массив через СтрРазделить, сборка массива обратно в строку, а также типичные ошибки — от нумерации с единицы до потери пустых элементов при разборе CSV-подобных данных.

Почему в 1С нельзя обратиться к символу по индексу

Строка во встроенном языке 1С — примитивный неизменяемый тип. Оператор квадратных скобок [] работает только с коллекциями: массивами, структурами, таблицами значений. Попытка написать Символ = Строка[1] завершится ошибкой «Индекс находится за границами массива» или ошибкой компиляции в зависимости от контекста.

Следствие неизменяемости: любая «замена символа» в строке фактически создаёт новую строку. Если нужно изменить один символ в середине, придётся склеить результат из трёх частей: Лев(Строка, Н-1) + НовыйСимвол + Сред(Строка, Н+1). Это важно учитывать при массовых обработках — конкатенация в цикле на длинных строках заметно расходует память и время.

Посимвольный перебор строки через цикл и Сред()

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

Строка = "Артикул-123";

ДлинаСтроки = СтрДлина(Строка);

Для Н = 1 По ДлинаСтроки Цикл

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

Если НЕ (Символ >= "0" И Символ <= "9") Тогда

Сообщить("Позиция " + Н + ": не цифра — " + Символ);

КонецЕсли;

КонецЦикла;

Такой цикл подходит для проверки состава строки: только цифры, только буквы, отсутствие пробелов и спецсимволов. Для проверки «только цифры» есть и альтернатива без цикла — функция СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке() из БСП, но в «голой» конфигурации её может не быть.

Обратите внимание: сравнение символов строками Символ >= "0" работает, потому что строки в 1С сравниваются лексикографически. Это рабочий, но не самый очевидный приём — для читаемости лучше вынести проверку в отдельную функцию с говорящим именем.

bsl
// Подсчёт цифр в строке
Функция КоличествоЦифр(Строка)
    Счетчик = 0;
    Для Н = 1 По СтрДлина(Строка) Цикл
        Символ = Сред(Строка, Н, 1);
        Если Символ >= "0" И Символ <= "9" Тогда
            Счетчик = Счетчик + 1;
        КонецЕсли;
    КонецЦикла;
    Возврат Счетчик;
КонецФункции

СтрРазделить: превращаем строку в настоящий массив

Функция СтрРазделить(Строка, Разделитель, ВключатьПустые) — самый короткий путь получить массив из строки. Она возвращает объект типа «Массив», с которым уже можно работать привычно: обращаться по индексу (с нуля!), перебирать в цикле Для Каждого, узнавать размер через Количество().

Части = СтрРазделить("Иванов;Иван;Иванович", ";");

// Части[0] = "Иванов", Части[1] = "Иван", Части[2] = "Иванович"

Сообщить(Части.Количество()); // 3

Третий параметр — ВключатьПустые — критичен при разборе CSV-подобных строк. По умолчанию он равен Истина, и строка "а;;в" даст три элемента, где средний — пустая строка. Если передать Ложь, пустые элементы пропадут, и позиционная привязка данных собьётся: Части[1] станет "в" вместо пустоты. При разборе файлов обмена, где важна позиция колонки, параметр опускать нельзя.

Разделитель может быть многосимвольным: СтрРазделить(Текст, Символы.ПС) разобьёт многострочный текст на массив строк. Это стандартный способ обработки текстовых файлов, прочитанных целиком через ЧтениеТекста.

Разбор строки на отдельные символы

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

МассивСимволов = Новый Массив;

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

МассивСимволов.Добавить(Сред(Строка, Н, 1));

КонецЦикла;

СтрСоединить: сборка массива обратно в строку

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

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

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

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

Очищенный = СокрЛП(Элемент);

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

Результат.Добавить(Очищенный);

КонецЕсли;

КонецЦикла;

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

Такая связка «разделить — обработать — соединить» читается лучше, чем ручная склейка строк в цикле с отслеживанием запятых, и меньше подвержена ошибкам с висячим разделителем в конце.

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

Строковые функции для работы с позициями: Лев, Прав, Сред, СтрНайти

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

  • Лев(Строка, 2) — первые два символа, например код региона;
  • Прав(Строка, 4) — последние четыре, например суффикс файла;
  • Сред(Строка, 3, 5) — пять символов начиная с третьего;
  • СтрНайти(Строка, "-") — позиция первого дефиса, чтобы отрезать по ней.

Комбинация СтрНайти + Лев/Сред решает задачу «взять часть до первого разделителя» без создания массива, что быстрее и короче, когда частей всего две:

Позиция = СтрНайти(Артикул, "-");

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

Префикс = Лев(Артикул, Позиция - 1);

Номер = Сред(Артикул, Позиция + 1);

КонецЕсли;

Важно проверять, что СтрНайти вернула значение больше нуля: если подстрока не найдена, функция возвращает 0, и Лев(Строка, -1) вызовет ошибку выполнения.

Производительность: когда посимвольный обход не подходит

Цикл со Сред на коротких строках (до нескольких сотен символов) работает мгновенно, и оптимизировать его не нужно. Проблемы начинаются на длинных текстах и массовых обработках: разбор файла на сотни тысяч строк с посимвольной проверкой каждой может занять заметное время.

Приёмы ускорения:

  • Заменить посимвольную проверку на СтрЗаменить: например, чтобы убрать все пробелы и проверить, что остались цифры, не нужен цикл;
  • Использовать СтрЧислоВхождений вместо цикла подсчёта конкретного символа;
  • Для сложных шаблонов — регулярные выражения через COM-объект VBScript.RegExp (на Windows-клиенте/сервере), если платформа и режим безопасности это позволяют;
  • Кэшировать СтрДлина(Строка) в переменную перед циклом, а не вызывать в условии каждой итерации — в современных версиях платформы это микрооптимизация, но код становится чище.

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

Цикл со Сред()

Подходит для посимвольного анализа и замен. Медленнее на длинных строках, многословнее.

СтрРазделить + массив

Лучший выбор при разборе по разделителю. Не работает для разбора на отдельные символы.

Лев/Прав/Сред + СтрНайти

Оптимально для жёстких форматов и отсечения одной части. Не масштабируется на много полей.

СтрЗаменить / СтрЧислоВхождений

Быстрая замена и подсчёт без цикла. Не подходит для позиционной логики.

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

Первая и главная — путаница в нумерации: символы строки считаются с 1, элементы массива — с 0. Когда в одном алгоритме смешаны Сред(Строка, Н, 1) и Массив[Н], данные неизбежно смещаются. Правило: выбрали один подход — держитесь его до конца функции.

Вторая — игнорирование пустых элементов и лишних пробелов после разделителя. Строка "а, б, в" при разборе по запятой даст элементы с ведущими пробелами. Всегда применяйте СокрЛП к каждому элементу, если данные пришли извне.

Третья — конкатенация строк в цикле вместо массива. Сборка результата через Итог = Итог + Символ на длинных строках создаёт тысячи промежуточных строк. Эффективнее накапливать части в массиве и один раз вызвать СтрСоединить.

Типичные ошибки
01
Обращение к Строка[0] — в 1С такой синтаксис не работает, строка не массив
02
Нумерация с нуля в Сред(): Сред(Строка, 0, 1) даёт ошибку или неверный результат, позиции начинаются с 1
03
Разбор позиционных данных с ВключатьПустые = Ложь — колонки съезжают
04
Отсутствие проверки результата СтрНайти: при нуле Лев(Строка, -1) падает с ошибкой
05
Склейка строки в цикле вместо массива + СтрСоединить — лишний расход памяти

Проверка результата и границы применения

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

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

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

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

Разбор тестовой строки
Норма

Количество элементов совпадает с ожидаемым, значения на своих позициях

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

Элементов меньше/больше, данные смещены на позицию

Пустая входная строка
Норма

Код отрабатывает без ошибки, возвращает осмысленный результат

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

Ошибка обращения по индексу или бесконечный цикл

Строка без разделителя
Норма

Получен массив из одного элемента с исходной строкой

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

Потеря данных или падение кода

Посимвольный обход
Норма

Обработаны все символы от первого до последнего

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

Первый или последний символ пропущен — ошибка границ цикла

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

Можно ли в 1С написать Строка[0] для получения первого символа?

Нет. Оператор индексации не применим к строкам. Первый символ получают через Лев(Строка, 1) или Сред(Строка, 1, 1). Если нужен именно массив символов, заполните его циклом со Сред.

Почему СтрРазделить вернула на один элемент больше, чем разделителей в строке?

Это нормально: N разделителей делят строку на N+1 частей. Строка "а;в;г" с двумя разделителями даёт три элемента. Если фактическое количество не совпадает с ожиданием, проверяйте параметр ВключатьПустые и наличие разделителя в конце строки.

Как удалить из строки все символы, кроме цифр, без цикла?

Полностью без цикла — сложно. В конфигурациях на БСП есть готовые функции общего модуля СтроковыеФункцииКлиентСервер. Вручную обычно делают цикл со Сред, добавляя в результат только символы от "0" до "9", либо используют регулярные выражения через COM-объект там, где он доступен.

Что быстрее: цикл со Сред или СтрРазделить?

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

Как разбить многострочный текст на массив строк?

Используйте СтрРазделить(Текст, Символы.ПС). Учтите, что в файлах, пришедших из Windows, перевод строки — это пара Символы.ВК + Символы.ПС, и после разбора в концах элементов могут остаться символы возврата каретки — их убирают через СтрЗаменить(Элемент, Символы.ВК, "") или СокрП.

Как заменить символ в конкретной позиции строки?

Строки неизменяемы, поэтому собирается новая: НоваяСтрока = Лев(Строка, Н-1) + НовыйСимвол + Сред(Строка, Н+1). Перед заменой убедитесь, что Н находится в диапазоне от 1 до СтрДлина(Строка).

Итог

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

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