Замена символов в строках — одна из самых частых задач при работе с данными в 1С:Предприятие. Без этого не обойтись при очистке данных, подготовке отчетов, интеграции с внешними системами или даже банальной корректировке пользовательского ввода. Однако в 1С есть несколько способов решить эту задачу, и выбор подходящего зависит от контекста: нужно ли заменить символы в запросе SQL, в модуле на встроенном языке или при обработке больших массивов данных.
В этой статье мы разберем все актуальные методы замены символов в строках 1С, включая стандартные функции, регулярные выражения и особенности работы с запросами. Вы узнаете, как заменить одиночные символы, подстроки, спецсимволы, а также как обработать большие тексты без потери производительности. Особое внимание уделим типичным ошибкам и нюансам, которые часто упускают даже опытные разработчики.
1. Стандартная функция СтрЗаменить(): синтаксис и примеры
Самый простой и распространенный способ замены символов в 1С 8.3 — встроенная функция СтрЗаменить(). Она работает как в тонком, так и в толстом клиенте, и подходит для большинства задач по обработке строк.
Синтаксис функции:
СтрЗаменить(ИсходнаяСтрока, СтараяПодстрока, НоваяПодстрока[, НаправлениеПоиска[, НачальнаяПозиция[, КоличествоЗамен]]])
Где:
- 📌 ИсходнаяСтрока — строка, в которой производится замена;
- 🔄 СтараяПодстрока — символ или подстрока, которую нужно заменить;
- ✨ НоваяПодстрока — символ или подстрока, на которую производится замена;
- 🔍 НаправлениеПоиска (необязательно) — направление поиска (
НаправлениеПоиска.НазадилиНаправлениеПоиска.Вперед, по умолчанию — вперед); - 📍 НачальнаяПозиция (необязательно) — позиция, с которой начинается поиск;
- 🔢 КоличествоЗамен (необязательно) — максимальное количество замен (по умолчанию — все вхождения).
Примеры использования:
// Замена всех точек на запятые
Результат = СтрЗаменить("123.45.67", ".", ",");
// Замена только первого вхождения
Результат = СтрЗаменить("abcabcabc", "a", "X", , , 1); // "Xbcabcabc"
// Замена с 3-й позиции
Результат = СтрЗаменить("123456789", "3", "0", , 3); // "120456789"
⚠️ Внимание: ФункцияСтрЗаменить()чувствительна к регистру! Если нужно заменить символы без учета регистра, используйтеНРег()или регулярные выражения.
2. Замена символов с помощью регулярных выражений
Если требуется сложная замена (например, по шаблону, с учетом регистра или специальных символов), на помощь приходят регулярные выражения. В 1С для этого используется объект РегВыражение.
Преимущества регулярных выражений:
- 🔧 Гибкость: можно задавать сложные шаблоны (например, заменить все цифры или символы в квадратных скобках);
- 🔠 Учет регистра: есть флаги для игнорирования регистра (
РегВыражение.ИгнорироватьРегистр); - 📝 Замена по группам: можно ссылаться на найденные группы в шаблоне замены.
Пример: замена всех цифр на звездочки (*):
РегВыр = Новый РегВыражение("\d");
Результат = РегВыр.Заменить("Товар123", "*"); // "Товар***"
Пример: замена всех пробелов и табуляций на один пробел:
РегВыр = Новый РегВыражение("\s+");
Результат = РегВыр.Заменить("Текст с лишними пробелами", " "); // "Текст с лишними пробелами"
⚠️ Внимание: Регулярные выражения работают медленнее СтрЗаменить() при простых заменах. Используйте их только когда стандартные функции не справляются.
Если нужно заменить символы в большом тексте (например, в XML или JSON), предварительно проверьте длину строки. Для строк длиной >10 000 символов лучше использовать посимвольную обработку в цикле, чтобы избежать зависаний.
3. Замена символов непосредственно в запросе 1С
Иногда замену символов удобнее сделать прямо в SQL-запросе, особенно если данные извлекаются из базы и сразу требуют обработки. Для этого в языке запросов 1С есть функция ВЫРАЖЕНИЕ (или CASE WHEN для условной замены).
Пример: замена точек на запятые в поле Артикул:
ВЫБРАТЬ
Номенклатура.Наименование,
ВЫРАЖЕНИЕ(ЗАМЕНИТЬ(Номенклатура.Артикул, ".", ",")) КАК АртикулСЗапятыми
ИЗ
Справочник.Номенклатура КАК Номенклатура
Пример с CASE WHEN (замена пустых значений на прочерк):
ВЫБРАТЬ
Контрагенты.Наименование,
ВЫБОР
КОГДА Контрагенты.ИНН = ""
ТОГДА "-"
ИНАЧЕ Контрагенты.ИНН
КОНЕЦ КАК ИНН
ИЗ
Справочник.Контрагенты КАК Контрагенты
Особенности замены в запросах:
- 🔹 Функция
ЗАМЕНИТЬв запросе аналогичнаСтрЗаменить(), но работает только с литералами; - 🔹 Для сложных замен (например, по регулярному выражению) придется использовать временные таблицы или обрабатывать данные после выборки;
- 🔹 Замена в запросе не влияет на исходные данные в базе — только на результат выборки.
| Метод | Пример кода | Когда использовать |
|---|---|---|
СтрЗаменить() |
СтрЗаменить("abc", "a", "X") |
Простые замены в модуле |
РегВыражение |
РегВыр.Заменить("123", "\d", "*") |
Сложные шаблоны, учет регистра |
ВЫРАЖЕНИЕ(ЗАМЕНИТЬ()) |
ВЫРАЖЕНИЕ(ЗАМЕНИТЬ(Поле, ".", ",")) |
Замена прямо в SQL-запросе |
4. Замена специальных символов (пробелы, табуляции, переводы строк)
При работе с текстами из внешних источников (например, Excel, XML или JSON) часто встречаются непечатаемые символы: табуляции (\t), переводы строк (\n, \r) или неразрывные пробелы ( ). Их замена требует особого подхода.
Примеры:
// Замена табуляций на запятые
Текст = "А"" ""Б"" ""В";
Результат = СтрЗаменить(Текст, Символы.Таб, ","); // "А,Б,В"
// Замена всех типов переводов строк на один символ
Текст = "Строка1
Строка2
Строка3";
РегВыр = Новый РегВыражение("\r\n|\r|\n");
Результат = РегВыр.Заменить(Текст, "; "); // "Строка1; Строка2; Строка3"
Для замены неразрывных пробелов используйте их код в Unicode:
Результат = СтрЗаменить(Текст, Символ(160), " "); // Замена на обычный пробел
⚠️ Внимание: Символы\nи\rв 1С представляются какСимволы.ПС(перевод строки) иСимволы.ВК(возврат каретки). Не путайте их с литералами "\n" в регулярных выражениях!
Удалить начальные и конечные пробелы (СокрЛП())
Заменить табуляции на запятые или пробелы
Нормализовать переводы строк (оставить только \n)
Проверить наличие непечатаемых символов (коды <32)
-->
5. Замена символов в больших текстах: оптимизация производительности
Если вам нужно обработать большой текст (например, XML-файл или JSON размером несколько мегабайт), стандартные функции могут работать медленно. В таких случаях помогают:
- 🔄 Посимвольная обработка в цикле — если замена простая (например, замена кавычек);
- 📖 Разбиение текста на части — обработка блоками по 10 000 символов;
- 🚀 Использование временных файлов — для крайне больших данных (например, при обмене с внешними системами).
Пример оптимизированной замены для большого текста:
Текст = ПолучитьБольшойТекст(); // Например, из файла
Результат = "";
ДлинаЧасти = 10000;
Для Смещение = 1 По СтрДлина(Текст) Цикл По ДлинаЧасти
Часть = Сред(Текст, Смещение, ДлинаЧасти);
Часть = СтрЗаменить(Часть, """", "'"); // Замена кавычек
Результат = Результат + Часть;
КонецЦикла;
Для критически важных операций (например, при обработке EDI-сообщений) лучше выносить замену символов на сторону SQL-сервера или использовать внешние компоненты.
Что делать если 1С зависает при замене в большом тексте?
Если при замене символов в строке длиной >50 000 символов 1С "подвисает", попробуйте:
1. Разбить текст на части по 5 000–10 000 символов и обрабатывать их отдельно.
2. Использовать регулярные выражения с флагом `РегВыражение.Многострочный` для обработки по строкам.
3. Выгрузить текст во временный файл, обработать его внешней утилитой (например, на PowerShell или Python), а затем загрузить обратно.
4. Если замена простая (например, один символ на другой), напишите собственную функцию на встроенном языке с посимвольным перебором — это часто работает быстрее, чем `СтрЗаменить()` для больших строк.
6. Типичные ошибки и как их избежать
Даже опытные разработчики 1С иногда допускают ошибки при замене символов. Вот самые распространенные:
- 🔥 Зацикливание при рекурсивной замене: если новая подстрока содержит старую, может возникнуть бесконечный цикл. Например, замена
"а"на"аа"в строке"а"приведет к зависанию. - 📛 Игнорирование регистра: функция
СтрЗаменить()учитывает регистр, поэтомуСтрЗаменить("АБВ", "а", "X")не даст результата. - 🗑️ Замена в пустых строках: если исходная строка пустая (
""), функция вернет ошибку при указании несуществующей позиции. - 🔄 Неправильное направление поиска: параметр
НаправлениеПоиска.Назадищет с конца строки, что может привести к неожиданным результатам.
Как избежать ошибок:
// Проверка на пустую строку
Если НЕ ПустаяСтрока(ИсходнаяСтрока) Тогда
Результат = СтрЗаменить(ИсходнаяСтрока, "...", ",");
КонецЕсли;
// Безопасная замена с учетом регистра
ИсходнаяСтрока = НРег(ИсходнаяСтрока);
Результат = СтрЗаменить(ИсходнаяСтрока, НРег("а"), "X");
⚠️ Внимание: При замене символов в данных, которые потом попадут в XML или JSON, обязательно экранируйте специальные символы (например,&,<,>). Для этого используйте функцииСтрЭкранироватьXML()илиСтрЭкранироватьJSON().
Всегда проверяйте результат замены на тестовых данных перед применением в рабочей базе. Особенно если речь идет о массовой обработке справочников или документов.
7. Практический пример: очистка артикулов от лишних символов
Рассмотрим реальную задачу: в справочнике Номенклатура артикулы хранятся в формате "AB-123/CD", а нужно привести их к виду "AB123CD" (убрать дефисы и слэши).
Решение с использованием СтрЗаменить():
Процедура ОчиститьАртикулы()
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Артикул = Выборка.Артикул;
Артикул = СтрЗаменить(Артикул, "-", "");
Артикул = СтрЗаменить(Артикул, "/", "");
Выборка.Артикул = Артикул;
Выборка.Записать();
КонецЦикла;
КонецПроцедуры
Решение с регулярным выражением (если формат артикулов более сложный):
Процедура ОчиститьАртикулыРегВыражением()
РегВыр = Новый РегВыражение("[-\/]"); // Шаблон для дефисов и слэшей
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Выборка.Артикул = РегВыр.Заменить(Выборка.Артикул, "");
Выборка.Записать();
КонецЦикла;
КонецПроцедуры
Если артикулы нужно очистить прямо в отчете, используйте запрос:
ВЫБРАТЬ
Номенклатура.Наименование,
ВЫРАЖЕНИЕ(ЗАМЕНИТЬ(ЗАМЕНИТЬ(Номенклатура.Артикул, "-", ""), "/", "")) КАК ОчищенныйАртикул
ИЗ
Справочник.Номенклатура КАК Номенклатура
FAQ: Частые вопросы по замене символов в 1С
Как заменить все вхождения подстроки, кроме первого?
Используйте параметр КоличествоЗамен в комбинации со Сред():
Строка = "абв-абв-абв";
ПервоеВхождение = Найти(Строка, "-");
Результат = СокрЛ(Строка) + Сред(Строка, ПервоеВхождение);
Результат = СтрЗаменить(Результат, "-", "", , ПервоеВхождение + 1); // "абв-абвабв"
Можно ли заменить символы в поле табличной части документа прямо в форме?
Да, но лучше делать это в модуле объекта или через обработку. Пример для формы:
Процедура ТабличнаяЧастьПриИзменении(Элемент)
Если Элемент.ТекущиеДанные.СодержитСтроку("-") Тогда
Элемент.ТекущиеДанные.Артикул = СтрЗаменить(Элемент.ТекущиеДанные.Артикул, "-", "");
КонецЕсли;
КонецПроцедуры
Обратите внимание: изменение данных в форме не сохраняет их в базе автоматически!
Как заменить кириллические символы на латинские (транслитерация)?
В 1С нет встроенной функции транслитерации, но можно написать собственную:
Функция Транслитерация(Текст)
Соответствие = Новый Соответствие;
Соответствие.Вставить("а", "a"); Соответствие.Вставить("б", "b"); // ... заполнить все буквы
Результат = "";
Для Каждого Символ Из Текст Цикл
Если Соответствие.Содержит(НРег(Символ)) Тогда
Результат = Результат + Соответствие[НРег(Символ)];
Иначе
Результат = Результат + Символ;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Для упрощения можно использовать готовые внешние компоненты или функции из БСП.
Почему СтрЗаменить() не заменяет символы в некоторых случаях?
Частые причины:
- Символы разного регистра (например, ищется "А", а в строке "а");
- В строке есть непечатаемые символы (пробелы, табуляции);
- Параметр
НачальнаяПозицияуказан за пределами строки; - Используется неверная кодировка (например, символы в UTF-8, а обрабатываются как Windows-1251).
Проверьте строку на наличие скрытых символов с помощью СтрДлина() и КодСимвола().
Как заменить символы в файле (например, CSV или TXT) без загрузки в память?
Для больших файлов используйте построчную обработку:
Чтение = Новый ЧтениеТекста(ПутьКФайлу);
Запись = Новый ЗаписьТекста(ПутьКРезультирующемуФайлу);
Пока Чтение.ПрочитатьСтроку() Цикл
Строка = СтрЗаменить(Чтение.ТекущаяСтрока, ";", "|");
Запись.ЗаписатьСтроку(Строка);
КонецЦикла;
Запись.Закрыть();