Разработка и Конфигурация · 13 мин
Строка как массив в 1С: обход символов и разбор строк
Как работать со строкой в 1С как с массивом символов: СтрДлина, Сред, СтрРазделить, перебор символов, типичные ошибки и примеры кода на встроенном языке.
В языке 1С нет прямого обращения к символу строки по индексу, как в C# или Python: конструкция Строка[0] вызовет ошибку. Тем не менее строку вполне можно обрабатывать как массив — для этого используются встроенные функции СтрДлина, Сред, Лев, Прав, а также СтрРазделить и СтрСоединить, которые преобразуют строку в настоящий массив подстрок и обратно.
Задача «пройтись по строке как по массиву» возникает постоянно: проверка ИНН посимвольно, разбор артикула по позициям, поиск недопустимых символов в наименовании, парсинг строк из обменных файлов. У каждого подхода — свои ограничения по производительности и читаемости, и выбирать их стоит осознанно.
В этом материале разобраны все рабочие способы: цикл по символам через Сред, разделение строки в массив через СтрРазделить, сборка массива обратно в строку, а также типичные ошибки — от нумерации с единицы до потери пустых элементов при разборе CSV-подобных данных.
Почему в 1С нельзя обратиться к символу по индексу
Строка во встроенном языке 1С — примитивный неизменяемый тип. Оператор квадратных скобок [] работает только с коллекциями: массивами, структурами, таблицами значений. Попытка написать Символ = Строка[1] завершится ошибкой «Индекс находится за границами массива» или ошибкой компиляции в зависимости от контекста.
Следствие неизменяемости: любая «замена символа» в строке фактически создаёт новую строку. Если нужно изменить один символ в середине, придётся склеить результат из трёх частей: Лев(Строка, Н-1) + НовыйСимвол + Сред(Строка, Н+1). Это важно учитывать при массовых обработках — конкатенация в цикле на длинных строках заметно расходует память и время.
Посимвольный перебор строки через цикл и Сред()
Базовый приём: определяем длину строки функцией СтрДлина и в цикле извлекаем каждый символ через Сред(Строка, Позиция, 1). Позиции нумеруются с единицы — это первая частая ошибка у тех, кто пришёл из других языков.
Строка = "Артикул-123";
ДлинаСтроки = СтрДлина(Строка);
Для Н = 1 По ДлинаСтроки Цикл
Символ = Сред(Строка, Н, 1);
Если НЕ (Символ >= "0" И Символ <= "9") Тогда
Сообщить("Позиция " + Н + ": не цифра — " + Символ);
КонецЕсли;
КонецЦикла;
Такой цикл подходит для проверки состава строки: только цифры, только буквы, отсутствие пробелов и спецсимволов. Для проверки «только цифры» есть и альтернатива без цикла — функция СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке() из БСП, но в «голой» конфигурации её может не быть.
Обратите внимание: сравнение символов строками Символ >= "0" работает, потому что строки в 1С сравниваются лексикографически. Это рабочий, но не самый очевидный приём — для читаемости лучше вынести проверку в отдельную функцию с говорящим именем.
// Подсчёт цифр в строке
Функция КоличествоЦифр(Строка)
Счетчик = 0;
Для Н = 1 По СтрДлина(Строка) Цикл
Символ = Сред(Строка, Н, 1);
Если Символ >= "0" И Символ <= "9" Тогда
Счетчик = Счетчик + 1;
КонецЕсли;
КонецЦикла;
Возврат Счетчик;
КонецФункцииСтрРазделить: превращаем строку в настоящий массив
Функция СтрРазделить(Строка, Разделитель, ВключатьПустые) — самый короткий путь получить массив из строки. Она возвращает объект типа «Массив», с которым уже можно работать привычно: обращаться по индексу (с нуля!), перебирать в цикле Для Каждого, узнавать размер через Количество().
Части = СтрРазделить("Иванов;Иван;Иванович", ";");
// Части[0] = "Иванов", Части[1] = "Иван", Части[2] = "Иванович"
Сообщить(Части.Количество()); // 3
Третий параметр — ВключатьПустые — критичен при разборе CSV-подобных строк. По умолчанию он равен Истина, и строка "а;;в" даст три элемента, где средний — пустая строка. Если передать Ложь, пустые элементы пропадут, и позиционная привязка данных собьётся: Части[1] станет "в" вместо пустоты. При разборе файлов обмена, где важна позиция колонки, параметр опускать нельзя.
Разделитель может быть многосимвольным: СтрРазделить(Текст, Символы.ПС) разобьёт многострочный текст на массив строк. Это стандартный способ обработки текстовых файлов, прочитанных целиком через ЧтениеТекста.
Разбор строки на отдельные символы
Если нужен массив именно символов, а не подстрок, СтрРазделить не поможет — пустой разделитель она не принимает. Варианты: цикл со Сред и добавлением в массив, либо разбор через СтрРазделить по символу, которого гарантированно нет в строке, не сработает. Практичный путь — заполнить массив вручную:
МассивСимволов = Новый Массив;
Для Н = 1 По СтрДлина(Строка) Цикл
МассивСимволов.Добавить(Сред(Строка, Н, 1));
КонецЦикла;
СтрСоединить: сборка массива обратно в строку
Обратная операция — СтрСоединить(Массив, Разделитель). Она склеивает элементы массива в одну строку через указанный разделитель. Типичный сценарий: разобрали строку в массив, обработали элементы (подрезали пробелы, отфильтровали лишние), собрали обратно.
Части = СтрРазделить(" яблоко ; груша ;сливa ", ";");
Результат = Новый Массив;
Для Каждого Элемент Из Части Цикл
Очищенный = СокрЛП(Элемент);
Если Не ПустаяСтрока(Очищенный) Тогда
Результат.Добавить(Очищенный);
КонецЕсли;
КонецЦикла;
Итог = СтрСоединить(Результат, ", "); // "яблоко, груша, сливa"
Такая связка «разделить — обработать — соединить» читается лучше, чем ручная склейка строк в цикле с отслеживанием запятых, и меньше подвержена ошибкам с висячим разделителем в конце.
- 1Определите разделитель и проверьте, может ли он встречаться внутри данных
- 2Вызовите СтрРазделить с явным третьим параметром ВключатьПустые
- 3Проверьте Количество() элементов до обращения по индексам
- 4Обработайте каждый элемент: СокрЛП, приведение типов, проверка пустоты
- 5Соберите результат через СтрСоединить, если нужна строка на выходе
Строковые функции для работы с позициями: Лев, Прав, Сред, СтрНайти
Не всякая задача требует массива. Если известны фиксированные позиции (формат строки жёсткий — например, штрихкод или код в старом формате обмена), достаточно функций среза:
Лев(Строка, 2)— первые два символа, например код региона;Прав(Строка, 4)— последние четыре, например суффикс файла;Сред(Строка, 3, 5)— пять символов начиная с третьего;СтрНайти(Строка, "-")— позиция первого дефиса, чтобы отрезать по ней.
Комбинация СтрНайти + Лев/Сред решает задачу «взять часть до первого разделителя» без создания массива, что быстрее и короче, когда частей всего две:
Позиция = СтрНайти(Артикул, "-");
Если Позиция > 0 Тогда
Префикс = Лев(Артикул, Позиция - 1);
Номер = Сред(Артикул, Позиция + 1);
КонецЕсли;
Важно проверять, что СтрНайти вернула значение больше нуля: если подстрока не найдена, функция возвращает 0, и Лев(Строка, -1) вызовет ошибку выполнения.
Производительность: когда посимвольный обход не подходит
Цикл со Сред на коротких строках (до нескольких сотен символов) работает мгновенно, и оптимизировать его не нужно. Проблемы начинаются на длинных текстах и массовых обработках: разбор файла на сотни тысяч строк с посимвольной проверкой каждой может занять заметное время.
Приёмы ускорения:
- Заменить посимвольную проверку на
СтрЗаменить: например, чтобы убрать все пробелы и проверить, что остались цифры, не нужен цикл; - Использовать
СтрЧислоВхожденийвместо цикла подсчёта конкретного символа; - Для сложных шаблонов — регулярные выражения через COM-объект
VBScript.RegExp(на Windows-клиенте/сервере), если платформа и режим безопасности это позволяют; - Кэшировать
СтрДлина(Строка)в переменную перед циклом, а не вызывать в условии каждой итерации — в современных версиях платформы это микрооптимизация, но код становится чище.
Сравнение вариантов
Подходит для посимвольного анализа и замен. Медленнее на длинных строках, многословнее.
Лучший выбор при разборе по разделителю. Не работает для разбора на отдельные символы.
Оптимально для жёстких форматов и отсечения одной части. Не масштабируется на много полей.
Быстрая замена и подсчёт без цикла. Не подходит для позиционной логики.
Типичные ошибки и как их избежать
Первая и главная — путаница в нумерации: символы строки считаются с 1, элементы массива — с 0. Когда в одном алгоритме смешаны Сред(Строка, Н, 1) и Массив[Н], данные неизбежно смещаются. Правило: выбрали один подход — держитесь его до конца функции.
Вторая — игнорирование пустых элементов и лишних пробелов после разделителя. Строка "а, б, в" при разборе по запятой даст элементы с ведущими пробелами. Всегда применяйте СокрЛП к каждому элементу, если данные пришли извне.
Третья — конкатенация строк в цикле вместо массива. Сборка результата через Итог = Итог + Символ на длинных строках создаёт тысячи промежуточных строк. Эффективнее накапливать части в массиве и один раз вызвать СтрСоединить.
Проверка результата и границы применения
После написания разбора проверьте код на граничных случаях: пустая строка, строка только из разделителей, один элемент без разделителя, разделитель в начале и в конце. СтрРазделить("", ";") вернёт массив с одним пустым элементом, а не пустой массив — это часто ломает логику проверок «если массив пустой».
Если формат входных строк сложный — вложенные кавычки, экранированные разделители, многоуровневая структура, — строковые функции перестают быть подходящим инструментом. Для JSON используйте ПрочитатьJSON, для XML — ЧтениеXML, для CSV со сложным экранированием имеет смысл написать отдельный парсер или использовать готовые библиотеки, а не наращивать цепочки СтрЗаменить.
Как проверить результат
Количество элементов совпадает с ожидаемым, значения на своих позициях
Элементов меньше/больше, данные смещены на позицию
Код отрабатывает без ошибки, возвращает осмысленный результат
Ошибка обращения по индексу или бесконечный цикл
Получен массив из одного элемента с исходной строкой
Потеря данных или падение кода
Обработаны все символы от первого до последнего
Первый или последний символ пропущен — ошибка границ цикла
Частые вопросы
Можно ли в 1С написать Строка[0] для получения первого символа?
Нет. Оператор индексации не применим к строкам. Первый символ получают через Лев(Строка, 1) или Сред(Строка, 1, 1). Если нужен именно массив символов, заполните его циклом со Сред.
Почему СтрРазделить вернула на один элемент больше, чем разделителей в строке?
Это нормально: N разделителей делят строку на N+1 частей. Строка "а;в;г" с двумя разделителями даёт три элемента. Если фактическое количество не совпадает с ожиданием, проверяйте параметр ВключатьПустые и наличие разделителя в конце строки.
Как удалить из строки все символы, кроме цифр, без цикла?
Полностью без цикла — сложно. В конфигурациях на БСП есть готовые функции общего модуля СтроковыеФункцииКлиентСервер. Вручную обычно делают цикл со Сред, добавляя в результат только символы от "0" до "9", либо используют регулярные выражения через COM-объект там, где он доступен.
Что быстрее: цикл со Сред или СтрРазделить?
СтрРазделить реализована на уровне платформы и заметно быстрее интерпретируемого цикла. Если задача сводится к разделению по разделителю — выбирайте её. Цикл со Сред оправдан только для посимвольной логики, которую разделителем не выразить.
Как разбить многострочный текст на массив строк?
Используйте СтрРазделить(Текст, Символы.ПС). Учтите, что в файлах, пришедших из Windows, перевод строки — это пара Символы.ВК + Символы.ПС, и после разбора в концах элементов могут остаться символы возврата каретки — их убирают через СтрЗаменить(Элемент, Символы.ВК, "") или СокрП.
Как заменить символ в конкретной позиции строки?
Строки неизменяемы, поэтому собирается новая: НоваяСтрока = Лев(Строка, Н-1) + НовыйСимвол + Сред(Строка, Н+1). Перед заменой убедитесь, что Н находится в диапазоне от 1 до СтрДлина(Строка).
Что важно запомнить
Строка в 1С — не массив: индексного доступа нет, символы нумеруются с 1. Посимвольный обход делается циклом со Сред(), разбор по разделителю — СтрРазделить с явным параметром ВключатьПустые, сборка — СтрСоединить. Всегда проверяйте Количество() массива перед обращением по индексу и результат СтрНайти перед срезом строки.