Работа со строками в 1С:Предприятие — одна из самых частых задач при разработке конфигураций, обработок и отчётов. Нередко требуется выделить из строки только нужную часть: первые символы, фрагмент по разделителю, текст между двумя маркерами или последнюю часть пути к файлу. В этой статье разберём все доступные способы извлечения подстрок — от базовых функций встроенного языка до продвинутых техник с регулярными выражениями.
Особенность работы со строками в 1С заключается в том, что здесь нет универсального метода вроде substring() из других языков программирования. Вместо этого используется набор специализированных функций, каждая из которых решает свою задачу. Мы покажем, как правильно применять Лев(), Прав(), Сред(), а также менее очевидные приёмы вроде разбора строк по шаблону или использования объекта Строка.
Статья будет полезна как начинающим разработчикам 1С, так и опытным программистам, которые хотят систематизировать знания или узнать о малоизвестных нюансах. Все примеры тестировались на платформах 1С:Предприятие 8.3.20 и 8.2.19, но большинство методов работают и в более ранних версиях.
1. Базовые функции для работы с подстроками: Лев(), Прав(), Сред()
Начнём с самого простого — встроенных функций, которые позволяют извлекать части строки по фиксированным позициям. Эти методы подходят, когда вы точно знаете длину нужного фрагмента или его положение в исходной строке.
Функция Лев(Строка, Количество) возвращает указанное количество символов с начала строки. Например, чтобы получить первые 3 символа из строки "АБВГД", используем:
Результат = Лев("АБВГД", 3); // Вернёт "АБВ"
Функция Прав(Строка, Количество) работает аналогично, но берёт символы с конца строки. Это удобно для извлечения расширений файлов или последних цифр в коде:
Расширение = Прав("отчёт.xlsx", 4); // Вернёт "xlsx"
Функция Сред(Строка, Начало, Длина) — самая гибкая из трёх. Она позволяет указать стартовую позицию и количество символов для извлечения. Нумерация начинается с 1, а не с 0, как в некоторых других языках программирования. Пример:
Фрагмент = Сред("123456789", 4, 3); // Вернёт "456"
- 🔹 Лев() — когда нужны символы с начала строки (префиксы, первые буквы).
- 🔹 Прав() — для работы с суффиксами (расширения файлов, последние цифры).
- 🔹 Сред() — если требуется фрагмент из середины строки по известным координатам.
⚠️ Внимание: При использовании Сред() Например,Сред("ABC", 2, 10)вернёт"BC", а не сгенерирует исключение.
Убедитесь, что строка не пустая|Проверьте, что запрашиваемая длина не превышает длину строки|Учитывайте регистр символов, если это важно|Для многобайтовых кодировок (UTF-8) длины могут отличаться-->
2. Поиск и извлечение подстроки по разделителю
Часто строки имеют определённую структуру с разделителями — запятыми, точками с запятой, слэшами или пробелами. Например, путь к файлу "C:\Documents\Отчёты\2026.xlsx" или строка с данными "Иванов;Иван;Иванович;1985". В таких случаях удобно использовать комбинацию функций Найти() и Сред().
Алгоритм простой:
- Найти позицию разделителя с помощью
Найти(Строка, Разделитель). - Извлечь подстроку от начала до разделителя (или от разделителя до конца).
Пример для пути к файлу:
Путь = "C:\Documents\Отчёты\2026.xlsx";
ПозицияПоследнегоСлэша = Найти(Путь, "\", НачальнаяПозиция = СтрДлина(Путь) - 10); // Ищем с конца
ИмяФайла = Прав(Путь, СтрДлина(Путь) - ПозицияПоследнегоСлэша);
Сообщить(ИмяФайла); // Выведет "2026.xlsx"
Для строк с несколькими разделителями (например, CSV) можно написать универсальную функцию, которая вернёт массив подстрок:
Функция РазбитьСтроку(Строка, Разделитель)
Результат = Новый Массив;
Начало = 1;
Позиция = Найти(Строка, Разделитель, Начало);
Пока Позиция > 0 Цикл
Результат.Добавить(Сред(Строка, Начало, Позиция - Начало));
Начало = Позиция + 1;
Позиция = Найти(Строка, Разделитель, Начало);
КонецЦикла;
Результат.Добавить(Сред(Строка, Начало));
Возврат Результат;
КонецФункции
- 📁 Пути к файлам — извлечение имени файла или папки.
- 📊 CSV/TSV данные — разбор строк с разделителями.
- 🔢 Составные коды — выделение частей артикулов (например,
"ABC-123-XYZ").
Если разделитель может встречаться внутри кавычек (например, в CSV с запятыми внутри полей), используйте специализированные парсеры или регулярные выражения для надёжного разбора.
3. Использование объекта "Строка" и его методов
В 1С:Предприятие 8.3 появился объект Строка, который предоставляет более удобные методы для работы с текстом по сравнению с глобальными функциями. Например, метод Подстрока() позволяет извлекать фрагменты с указанием начальной позиции и длины, аналогично Сред(), но с более читаемым синтаксисом.
Примеры использования:
Текст = Новый Строка("Пример строки для обработки");
// Извлечь подстроку с 8-го символа длиной 5
Фрагмент = Текст.Подстрока(8, 5); // Вернёт "строк"
// Найти позицию подстроки
Позиция = Текст.Найти("для"); // Вернёт 16 (нумерация с 1)
// Разбить строку по разделителю
Части = Текст.Разделить(" "); // Вернёт массив ["Пример", "строки"..]
Преимущества объекта Строка:
- 🔧 Цепочка вызовов — можно комбинировать методы (например,
Текст.Подстрока(..).Заменить(..)). - 📏 Удобная работа с позициями — методы возвращают объекты, поддерживающие дальнейшие операции.
- 🔄 Поддержка Unicode — корректно обрабатывает многобайтовые символы.
Однако в 1С 8.2 объект Строка отсутствует, поэтому для совместимости с устаревшими конфигурациями придётся использовать глобальные функции.
⚠️ Внимание: Метод Разделить() объектаСтрокаигнорирует пустые элементы, если разделитель встречается подряд. Например,"а,,в".Разделить(",")вернёт массив из двух элементов["а", "в"], а не трёх. Если нужны все позиции, используйте цикл сНайти().
4. Регулярные выражения для сложных шаблонов
Когда строка имеет сложную структуру или разделители нефиксированные, на помощь приходят регулярные выражения. В 1С они доступны через объект РегулярноеВыражение (начиная с версии 8.3.6). Этот метод позволяет гибко извлекать данные по шаблону, например:
- 📧 Адреса электронной почты из текста.
- 🔢 Числа в произвольном формате (с разделителями, знаками валют).
- 📁 Пути к файлам с переменной структурой.
Пример: извлечём все email-адреса из текста:
Текст = "Контакты: ivanov@mail.ru, petrov@example.com, sidorov@company.org";
РегВыр = Новый РегулярноеВыражение("(\S+@\S+)");
Результаты = РегВыр.НайтиВсе(Текст);
Для Каждого Найденное Из Результаты Цикл
Сообщить(Найденное.Значение); // Выведет каждый email
КонецЦикла;
Более сложный пример — извлечение чисел с плавающей запятой из строки с текстом:
Текст = "Стоимость: 1 234,56 руб., скидка 10%, итого 1 111,11 руб.";
РегВыр = Новый РегулярноеВыражение("(\d[\d\s]*,\d{2})");
Результаты = РегВыр.НайтиВсе(Текст);
// Результаты: "1 234,56", "1 111,11"
Регулярные выражения незаменимы, когда:
- 🔍 Нужно найти текст по сложному шаблону (например, даты в формате
ДД.ММ.ГГГГсреди другого текста). - 📌 Структура строки нефиксированная или содержит вариативные разделители.
- 🔄 Требуется замена или валидация данных по маске.
⚠️ Внимание: Регулярные выражения в 1С поддерживаются не во всех версиях платформы. В конфигурациях для 1С 8.2 или устаревших релизах 8.3 этот метод недоступен. Проверьте совместимость перед использованием!
Как ускорить работу с регулярными выражениями?
Если вам часто приходится применять одно и то же регулярное выражение, создайте его один раз как переменную модуля (например, в общей области). Это сократит время компиляции шаблона при повторных вызовах. Пример:
Перем мРегВырПочта;
..
Если мРегВырПочта = Неопределено Тогда
мРегВырПочта = Новый РегулярноеВыражение("(\S+@\S+)");
КонецЕсли;
5. Практические примеры: извлечение данных из реальных строк
Рассмотрим несколько типовых задач, с которыми сталкиваются разработчики 1С, и оптимальные способы их решения.
| Задача | Пример строки | Решение | Результат |
|---|---|---|---|
| Извлечь домен из email | "user.name@company.ru" |
|
"company.ru" |
| Получить расширение файла | "document_2026.pdf" |
|
"pdf" |
| Выделить ФИО из строки | "Иванов Иван Иванович" |
|
"Иванов" |
| Извлечь номер документа | "Договор №АБВ-123/2026" |
|
"АБВ-123/2026" |
Для извлечения даты из строки с произвольным текстом (например, "Заказ от 15.05.2026 на сумму 1000 руб.") удобно комбинировать регулярные выражения с функцией Дата():
РегВыр = Новый РегулярноеВыражение("(\d{2}\.\d{2}\.\d{4})");
Найденное = РегВыр.Найти(Текст);
Если Найденное.Найдено Тогда
ДатаЗаказа = Дата(Найденное.Значение);
КонецЕсли;
Важно: При работе с датами в строках всегда учитывайте формат даты в настройках пользователя (через "dd.mm.yyyy" или "mm.dd.yyyy"). Используйте функцию ТекстВДату() с явным указанием формата, если строка может содержать неоднозначные даты (например, "01.02.2026").
Базовые функции (Лев/Прав/Сред)|Объект "Строка" и его методы|Регулярные выражения|Собственные функции с Найти()|Другой вариант-->
6. Ошибки и ловушки при работе с подстроками
Даже в простых операциях со строками легко допустить ошибку, которая приведёт к некорректным результатам или падению программы. Рассмотрим типичные проблемы и способы их избежать.
- 🚫 Пустые строки или ненайденные разделители:
Если в строке нет искомого разделителя, функция
Найти()вернёт 0. Это приведёт к ошибке при попытке извлечь подстроку. Всегда проверяйте результатНайти():Позиция = Найти(Строка, Разделитель);Если Позиция = 0 Тогда
// Обработать ошибку
КонецЕсли;
- 🚫 Многобайтовые символы (Unicode):
Функции вроде
СтрДлина()считают количество символов, а не байт. Для строк с кириллицей, иероглифами или эмодзи это может привести к неожиданным результатам при обрезке. Используйте объектСтрокадля надёжной работы с Unicode. - 🚫 Неучтённые пробелы или регистр:
При сравнении или поиске подстрок регистр символов имеет значение. Используйте
СтрНачинаетсяС(),СтрСодержит()или приводите строки к одному регистру с помощьюНРег()/ВРег().
Ещё одна распространённая ошибка — неверная обработка пустых результатов. Например, если в строке нет второго разделителя, код может попытаться извлечь подстроку за пределами строки. Защититесь от этого с помощью проверок:
Функция ПолучитьПодстрокуМежду(Строка, Разделитель1, Разделитель2)
Позиция1 = Найти(Строка, Разделитель1);
Если Позиция1 = 0 Тогда Возврат ""; КонецЕсли;
Позиция2 = Найти(Строка, Разделитель2, Позиция1 + 1);
Если Позиция2 = 0 Тогда Возврат ""; КонецЕсли;
Возврат Сред(Строка, Позиция1 + 1, Позиция2 - Позиция1 - 1);
КонецФункции
⚠️ Внимание: При работе с большими текстами (например, XML или JSON в строках) избегайте многократного вызова Найти() в циклах. Это может значительно замедлить выполнение. В таких случаях лучше использовать специализированные парсеры или регулярные выражения.
7. Оптимизация производительности при работе со строками
Если ваш код обрабатывает большое количество строк (например, в цикле по табличной части документа), стоит задуматься об оптимизации. Вот несколько советов:
- 🔄 Кэшируйте результаты: Если одна и та же строка обрабатывается многократно, сохраните промежуточные результаты (например, позиции разделителей) в переменные.
- 📌 Используйте объект "Строка": Его методы работают быстрее глобальных функций за счёт внутренних оптимизаций платформы.
- 🚀 Избегайте вложенных циклов: Например, при разборе CSV не вызывайте
Найти()для каждой строки в цикле — лучше разбейте строку на массив один раз.
Пример оптимизированного разбора строки с разделителями:
// Неэффективно (многократный вызов Найти)
Для i = 1 По 1000 Цикл
Позиция = Найти(БольшаяСтрока, Разделитель, Начало);
//..
КонецЦикла;
// Эффективно (разбиваем строку один раз)
МассивЧастей = СтрРазделить(БольшаяСтрока, Разделитель);
Для Каждого Часть Из МассивЧастей Цикл
// Обработка каждой части
КонецЦикла;
Для действительно больших текстов (мегабайты данных) рассмотрите возможность использования временных файлов или потоков (ЧтениеТекста/ЗаписьТекста), вместо хранения всего текста в памяти.
При работе с тысячами строк даже микрооптимизации (например, замена Лев(Стр, 1) на Стр[0]) могут дать заметный прирост производительности.
FAQ: Частые вопросы по извлечению подстрок в 1С
Как извлечь текст между двумя одинаковыми разделителями, например, между двумя кавычками?
Используйте комбинацию функций Найти() и Сред() с учётом сдвига позиции:
Функция ТекстМеждуКавычками(Строка)
Позиция1 = Найти(Строка, """");
Если Позиция1 = 0 Тогда Возврат ""; КонецЕсли;
Позиция2 = Найти(Строка, """", Позиция1 + 1);
Если Позиция2 = 0 Тогда Возврат ""; КонецЕсли;
Возврат Сред(Строка, Позиция1 + 1, Позиция2 - Позиция1 - 1);
КонецФункции
Для сложных случаев (например, с экранированными кавычками) лучше использовать регулярные выражения.
Почему функция Сред() возвращает пустую строку, хотя позиция вроде бы верная?
Вероятные причины:
- Указана позиция больше длины строки (функция вернёт пустоту без ошибки).
- Передана отрицательная длина (например, при ошибке в расчёте
Позиция2 - Позиция1). - В строке есть невидимые символы (пробелы, табуляции), смещающие позиции.
Проверьте длину строки с помощью СтрДлина() и выведите отладочную информацию.
Как разделить строку на слова, если разделитель — несколько пробелов или табуляции?
Используйте регулярное выражение с шаблоном \s+ (один или более пробельных символов):
РегВыр = Новый РегулярноеВыражение("\s+");
Слова = РегВыр.Разбить(Строка);
Или замените все пробелы на один перед разбором:
Строка = СтрЗаменить(Строка, " ", " "); // Замена двойных пробелов
Строка = СтрЗаменить(Строка, Символы.Таб, " "); // Замена табуляций
Можно ли в 1С 8.2 использовать регулярные выражения?
Нет, объект РегулярноеВыражение появился только в 1С:Предприятие 8.3.6. Для старых версий платформы придётся:
- Использовать внешние COM-объекты (например,
VBScript.RegExpна Windows). - Писать собственные функции для простых шаблонов.
- Обновить платформу, если это возможно.
Пример с COM-объектом (только для Windows):
Попытка
RegEx = Новый COMОбъект("VBScript.RegExp");
RegEx.Pattern = "\d+";
Результаты = RegEx.Execute(Строка);
Исключение
Сообщить("Ошибка: " + ОписаниеОшибки());
КонецПопытки;
Как извлечь подстроку, если разделитель — перенос строки?
Используйте символ Символы.ПС (перевод строки) или Символы.ВК (возврат каретки). Для универсальности замените все варианты переноса на один символ перед разбором:
Строка = СтрЗаменить(Строка, Символы.ВК, Символы.ПС); // Замена \r на \n
Строка = СтрЗаменить(Строка, Символы.ВК + Символы.ПС, Символы.ПС); // Замена \r\n на \n
МассивСтрок = СтрРазделить(Строка, Символы.ПС);