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

Особенность в том, что здесь нет универсального метода на все случаи жизни. Например, простая замена точки на запятую в числовом формате может обернуться ошибкой, если не учесть региональные настройки системы. А попытка заменить символ в строке с юникод-символами (например, эмодзи или иероглифами) часто приводит к "обрезке" строки. Мы покажем, как избежать таких ловушек и выбрать оптимальный метод для вашей задачи.

1. Базовый метод: функция СтрЗаменить()

Самый простой и распространённый способ — встроенная функция СтрЗаменить(). Она подходит для 90% задач, где нужно заменить один символ на другой в известной позиции или все вхождения в строке.

Синтаксис функции:

СтрЗаменить(ИсходнаяСтрока, СтарыйСимвол, НовыйСимвол[, НачальнаяПозиция[, КоличествоЗамен]])
  • 🔹 ИсходнаяСтрока — строка, в которой производится замена
  • 🔹 СтарыйСимвол — символ (или подстрока), который нужно заменить
  • 🔹 НовыйСимвол — символ (или подстрока), на который заменяем
  • 🔹 НачальнаяПозиция (необязательно) — с какой позиции начинать поиск (по умолчанию 1)
  • 🔹 КоличествоЗамен (необязательно) — сколько замен сделать (по умолчанию все вхождения)

Примеры использования:

// Замена всех точек на запятые (актуально для числовых форматов)

Результат = СтрЗаменить("123.456.789", ".", ",");

// Замена только первой точки

Результат = СтрЗаменить("2023.12.31", ".", "-", 1, 1); // Вернёт "2023-12.31"

// Замена подстроки (не только одного символа)

Результат = СтрЗаменить("Иванов И.И.", "И.", "Иван");

⚠️ Внимание: Функция СтрЗаменить() чувствительна к регистру! Замена "А" на "Б" не затронет символ "а". Для регистронезависимой замены используйте НРег() или регулярные выражения.
💡

Если вам нужно заменить символ в конкретной позиции строки (например, 3-й символ), используйте комбинацию Лев() + Прав() + Сред(). Пример: НоваяСтрока = Лев(ИсходнаяСтрока, 2) + "X" + Прав(ИсходнаяСтрока, СтрДлина(ИсходнаяСтрока) - 3);

2. Замена символа по позиции: Сред() + конкатенация

Когда нужно заменить символ на конкретной позиции в строке (например, исправить опечатку в 5-м символе), функция СтрЗаменить() не всегда удобна. В таких случаях лучше работать с частями строки:

Алгоритм:

  1. Разбиваем строку на три части: левая часть (до заменяемого символа), сам символ, правая часть (после символа)
  2. Заменяем среднюю часть на новый символ
  3. Склеиваем строку обратно

Пример кода:

Функция ЗаменитьСимволПоПозиции(Строка, Позиция, НовыйСимвол)

Возврат Лев(Строка, Позиция - 1) + НовыйСимвол + Прав(Строка, СтрДлина(Строка) - Позиция);

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

// Пример использования:

ИсходнаяСтрока = "123456789";

НоваяСтрока = ЗаменитьСимволПоПозиции(ИсходнаяСтрока, 4, "X"); // Вернёт "123X56789"

МетодПлюсыМинусыКогда использовать
СтрЗаменить()Простота, встроенная функцияНеудобно для замены по позицииЗамена всех вхождений символа
Сред() + конкатенацияТочная замена по позицииБольше кода, риск ошибок при вычислении длинИсправление опечаток в известных позициях
Регулярные выраженияМаксимальная гибкостьСложный синтаксис, производительностьСложные шаблоны замены

Этот метод особенно полезен при работе с фиксированными форматами (например, в банковских выписках или штрихкодах), где каждый символ имеет строгое значение. Например, если в 10-м символе кода товара всегда должен быть контрольный разряд, его можно динамически пересчитывать и подставлять.

📊 Какой метод замены символов вы используете чаще?
СтрЗаменить()
Сред()+конкатенация
Регулярные выражения
Своя функция

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

Если вам нужно заменить символы по сложному шаблону (например, все цифры после буквы "А" или символы в определённом контексте), на помощь приходят регулярные выражения. В 1С 8.3 для этого используется объект РегулярноеВыражение.

Примеры задач, где регулярные выражения незаменимы:

  • 📌 Замена всех цифр в строке на звёздочки (например, для маскировки номеров телефонов)
  • 📌 Удаление всех символов, кроме букв и цифр (очистка строки)
  • 📌 Замена символов с учётом контекста (например, точки только между цифрами)

Пример кода:

РегВыр = Новый РегулярноеВыражение("\d");  // Все цифры

Результат = РегВыр.Заменить("Абв123Где45", "*"); // Вернёт "Абв*Где"

// Замена точек на запятые ТОЛЬКО в числовых форматах (между цифрами)

РегВыр = Новый РегулярноеВыражение("(?<=\d)\.(?=\d)");

Результат = РегВыр.Заменить("12.345.678,90 руб.", ","); // Вернёт "12,345,678,90 руб."

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

Если вам нужно применить одно и то же регулярное выражение многократно (например, в цикле), создавайте объект РегулярноеВыражение ОДИН РАЗ до цикла, а не на каждой итерации. Это сократит время выполнения в 3-5 раз.

4. Работа с многобайтовыми символами (юникод)

Особую осторожность нужно проявлять при замене многобайтовых символов (кириллица, иероглифы, эмодзи). Дело в том, что функции вроде СтрДлина() и Сред() в работают с байтами, а не с символами. Например, строка "Привет😊" имеет длину 7 символов, но СтрДлина() вернёт 9 (так как эмодзи занимает 4 байта).

Как правильно работать с такими строками:

  • 🌍 Используйте функцию СтрЧислоСимволов() вместо СтрДлина() для получения количества символов
  • 🌍 Для извлечения подстроки используйте СтрПолучитьСтроку() с параметром "символ"
  • 🌍 При замене учитывайте, что некоторые символы (например, комбинируемые диакритические знаки) могут занимать несколько позиций

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

Функция ЗаменитьСимволЮникод(Строка, Позиция, НовыйСимвол)

// Преобразуем строку в массив символов

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

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

МассивСимволов.Добавить(СтрПолучитьСтроку(Строка, Инд, 1));

КонецЦикла;

// Заменяем нужный символ

МассивСимволов[Позиция - 1] = НовыйСимвол;

// Склеиваем обратно

Возврат СтрСокрЛП(СокрЛП(МассивСимволов.Склеить("")));

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

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

5. Замена символов в файлах и потоках

Иногда требуется заменить символы не в строковой переменной, а непосредственно в файле или потоке данных (например, при обработке выгружаемых/загружаемых файлов). Для этого в есть объекты ТекстовыйДокумент и Поток.

Пример замены символов в текстовом файле:

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

Текст = Новый ТекстовыйДокумент;

Текст.Прочитать("C:\data\input.txt");

// Замена всех точек на запятые

Текст.УстановитьТекст(СтрЗаменить(Текст.ПолучитьТекст(), ".", ","));

// Сохранение результата

Текст.Записать("C:\data\output.txt");

Для работы с большими файлами (более 100 МБ) лучше использовать Поток, чтобы не грузить всю строку в память:

Чтение = Новый ЧтениеТекста("C:\data\large_file.txt");

Запись = Новый ЗаписьТекста("C:\data\large_file_processed.txt");

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

Строка = Чтение.ТекущаяСтрока;

Запись.ЗаписатьСтроку(СтрЗаменить(Строка, "|", ";"));

КонецЦикла;

⚠️ Внимание: При работе с файлами в кодировке UTF-8 функция СтрЗаменить() может неправильно обрабатывать многобайтовые символы. В таких случаях предварительно преобразуйте строку в UTF-16 с помощью СтрокаВДвоичныеДанные() и ДвоичныеДанныеВСтроку().

6. Обработка ошибок и исключительные ситуации

Даже в простой операции замены символов могут возникать ошибки. Рассмотрим типичные проблемы и как их избежать:

  • 🚨 Позиция за пределами строки: Если указать позицию больше длины строки, не выдаст ошибку, но и замены не произойдёт. Всегда проверяйте длину строки перед заменой.
  • 🚨 Несовместимые кодировки: При работе с файлами или внешними системами символы могут "ломаться" из-за неверной кодировки. Используйте ТекстовыйДокумент.УстановитьКодировку().
  • 🚨 Null-значения: Если в строку попадёт Null, попытка замены приведёт к ошибке. Проверяйте на ЗначениеЗаполнено().
  • 🚨 Блокировка файлов: При работе с файлами убедитесь, что они не открыты в других программах.

Пример защищённого кода для замены символа:

Функция БезопаснаяЗаменаСимвола(Строка, СтарыйСимвол, НовыйСимвол)

Если НЕ ЗначениеЗаполнено(Строка) Тогда

Возврат Неопределено;

КонецЕсли;

Попытка

Возврат СтрЗаменить(Строка, СтарыйСимвол, НовыйСимвол);

Исключение

ЗаписатьЖурналРегистрации(НСтр("ru = 'Ошибка замены символа'"), УровеньЖурналаРегистрации.Ошибка);

Возврат Строка; // Возвращаем исходную строку при ошибке

КонецПопытки;

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

Для отладки сложных замен полезно использовать Сообщить() или ЗаписатьЖурналРегистрации(), чтобы видеть промежуточные результаты:

Сообщить("Исходная строка: " + ИсходнаяСтрока);

Сообщить("Результат замены: " + СтрЗаменить(ИсходнаяСтрока, "а", "о"));

💡

Всегда тестируйте замену символов на реальных данных перед применением в боевой базе. Особенно это касается работы с файлами и внешними системами, где ошибка может привести к потере данных.

7. Практический пример: очистка строки от недопустимых символов

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

Решение с использованием регулярного выражения:

Функция ОчиститьСтроку(ИсходнаяСтрока)

// Разрешаем: буквы, цифры, пробел, запятая, точка, тире

РегВыр = Новый РегулярноеВыражение("[^а-яА-ЯёЁa-zA-Z0-9 ,\.\-]");

Возврат РегВыр.Заменить(ИсходнаяСтрока, "");

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

// Пример использования:

ГрязнаяСтрока = "Привет! Это "тестовая" строка с #символами@.";

ЧистаяСтрока = ОчиститьСтроку(ГрязнаяСтрока); // Вернёт "Привет Это тестовая строка с символами."

Альтернативное решение без регулярных выражений (быстрее для больших объёмов):

Функция ОчиститьСтрокуБезРегВыра(ИсходнаяСтрока)

РазрешенныеСимволы = "абвгдеёжзийклмнопрстуфхцчшщъыьэюяabcdefghijklmnopqrstuvwxyz0123456789 ,.-";

Результат = "";

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

ТекущийСимвол = Сред(ИсходнаяСтрока, Инд, 1);

Если Найти(РазрешенныеСимволы, ТекущийСимвол) > 0 Тогда

Результат = Результат + ТекущийСимвол;

КонецЕсли;

КонецЦикла;

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

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

Для оптимизации производительности можно заранее создать Соответствие с разрешёнными символами и проверять наличие через Соответствие.Свойство().

☑️ Проверка перед очисткой строки

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

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

Как заменить символ в строке, если его позиция неизвестна, но известен шаблон?

Используйте регулярные выражения с шаблоном. Например, чтобы заменить первую цифру после буквы "А", используйте:

РегВыр = Новый РегулярноеВыражение("А\d");

Результат = РегВыр.Заменить("А1Б2В3", "АX"); // Вернёт "АXБ2В3"

Почему после замены символов в строке появляются "кракозябры"?

Это признак проблемы с кодировкой. Убедитесь, что:

  • Исходная строка и целевая кодировка совпадают (например, обе в UTF-8)
  • При чтении/записи файлов явно указана кодировка: ТекстовыйДокумент.УстановитьКодировку(КодировкаТекста.UTF8)
  • В базе данных поле имеет достаточный размер для многобайтовых символов
Как заменить символ в строке, хранящейся в базе данных?

Не извлекайте строку, меняйте её и сохраняйте обратно — это неэффективно. Используйте запрос с функцией ЗАМЕНИТЬ():

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| ЗАМЕНИТЬ(Ссылка.Наименование, ""."", ""-"") КАК НовоеНаименование

|ИЗ

| Справочник.Номенклатура КАК Ссылка

|ГДЕ

| Ссылка.Наименование ПОДОБНО ""%.%""";

Результат = Запрос.Выполнить();

Для обновления данных:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ РАЗРЕШЕННЫЕ ЗАМЕНИТЬ(Наименование, ""."", ""-"")

|ИЗ Справочник.Номенклатура

|ГДЕ Наименование ПОДОБНО ""%.%""";

Запрос.Выполнить();

Можно ли заменить символ в строке, не создавая новую строку?

Нет, в строки неизменяемы (immutable). Любая операция замены создаёт новую строку в памяти. Если вам критично экономить память, работайте с массивами символов или объектами ТекстовыйДокумент, которые позволяют редактировать текст "на месте".

Как заменить символ в строке с учётом регистра?

Функция СтрЗаменить() чувствительна к регистру. Чтобы заменить символы независимо от регистра:

// Вариант 1: Привести обе строки к одному регистру

СтрокаДляПоиска = НРег(ИсходнаяСтрока);

Позиция = Найти(СтрокаДляПоиска, НРег(СтарыйСимвол));

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

Результат = Лев(ИсходнаяСтрока, Позиция - 1) + НовыйСимвол + Прав(ИсходнаяСтрока, СтрДлина(ИсходнаяСтрока) - Позиция);

КонецЕсли;

// Вариант 2: Использовать регулярное выражение с флагом "i" (ignore case)

РегВыр = Новый РегулярноеВыражение("(?i)а"); // Заменит и "А", и "а"

Результат = РегВыр.Заменить("Апельсин и апельсин", "о"); // Вернёт "Опельсин и опельсин"