При выгрузке текстовых данных во внешние файлы (например, форматы CSV, XML или TXT) разработчики часто сталкиваются с необходимостью подготовки текстовых полей. Одной из самых распространенных задач является экранирование спецсимволов, в частности — удвоение двойных кавычек внутри строки (например, при выгрузке маркированных кодов SGTIN, артикулов с дюймами или сложных наименований номенклатуры). В среде 1С:Предприятие 7.7 эта задача имеет свои уникальные особенности, подводные камни и даже скрытые платформенные лайфхаки.
В этой статье мы подробно разберем, почему стандартные попытки замены кавычек могут не работать, как правильно использовать встроенные функции платформы, а также рассмотрим элегантные альтернативные методы, которые помогут сделать ваш код быстрее, чище и производительнее.
Разберем типичную ошибку начинающих разработчиков, с которой столкнулся автор темы на форуме. Первоначальный вариант кода выглядел следующим образом:
НайденныйСимвол = Найти(SGTIN, """");
Если НайденныйСимвол > 1 Тогда
СтрЗаменить(SGTIN, """", """""");
Файл.ДобавитьСтроку("""" + СокрЛП(SGTIN) + """" + ",," + Цена + "," + СуммаНДС);
КонецЕсли;
При проверке выяснилось, что код выполняется без ошибок, однако исходная строка в переменной SGTIN никак не изменяется. Выясним причину такого поведения платформы.
Дело в том, что строки в системе 1С:Предприятие (как в версии 7.7, так и в современных версиях 8.x) являются неизменяемым типом данных (immutable). Это означает, что любая встроенная функция манипуляции со строками не может изменить исходную переменную "на месте" (in-place) в оперативной памяти. Вместо этого функция обрабатывает данные, создает в памяти абсолютно новую строку и возвращает её в качестве результата своей работы.
Чтобы изменения вступили в силу, результат работы функции необходимо явно присвоить обратно в переменную либо сразу передать в метод выгрузки. Посмотрим на правильные варианты реализации:
// Вариант 1: Сохранение результата в исходную переменную перед записью
SGTIN = СтрЗаменить(SGTIN, """", """""");
Файл.ДобавитьСтроку("""" + СокрЛП(SGTIN) + """" + ",," + Цена + "," + СуммаНДС);
// Вариант 2: Замена "на лету" непосредственно при формировании строки для файла
Файл.ДобавитьСтроку("""" + СтрЗаменить(СокрЛП(SGTIN), """", """""") + """" + ",," + Цена + "," + СуммаНДС);
Конструкции в коде вида """" (четыре кавычки подряд для обозначения одного символа кавычки) или """""" (шесть кавычек для обозначения двух кавычек) программисты часто называют "синтаксическим кошмаром". В них крайне легко запутаться при написании кода, их тяжело визуально анализировать при отладке, а малейшая опечатка приведет либо к синтаксической ошибке компилятора, либо к трудноуловимому багу в логике программы.
Чтобы сделать код чистым, понятным и профессиональным, мы рекомендуем использовать встроенную функцию Симв(). Данная функция возвращает символ по его ASCII-коду. Код стандартной двойной кавычки в таблице ASCII — 34.
Давайте проанализируем, как преобразится наш код, если мы применим данный подход:
// Объявляем понятные переменные-константы
Кавычка = Симв(34);
ДвеКавычки = Кавычка + Кавычка;
// Выполняем замену, которая читается без напряжения глаз
SGTIN = СтрЗаменить(SGTIN, Кавычка, ДвеКавычки);
Такой код гораздо проще поддерживать другим разработчикам, и в нем физически невозможно ошибиться с количеством кавычек.
В ходе обсуждения на форуме был предложен крайне изящный способ экранирования кавычек через встроенный механизм сериализации данных платформы. Для разработчиков, не знакомых с тонкостями платформы 1С 7.7, этот код выглядит как набор случайных чисел, но за ним скрывается мощное и быстрое решение.
В платформе 1С 7.7 существует системная функция ЗначениеВСтроку(), которая преобразует любой объект базы данных или внутренний тип в текстовый системный формат. Если передать в эту функцию обычную строку, то платформа упакует её по внутренним правилам сериализации. Рассмотрим пример:
// Допустим, у нас есть строка:
стр = "Тестовая строка: "" - это кавычка";
// Системное представление этой строки после ЗначениеВСтроку(стр) примет вид:
// {"Строка","Тестовая строка: "" - это кавычка"}
Обратите внимание на ключевой момент: Платформа 1С на уровне своего ядра (написанного на высокопроизводительном C++) при сериализации сама гарантированно и корректно находит все двойные кавычки внутри текста и удваивает их, чтобы не нарушить структуру собственного формата. Нам остается лишь программно убрать "лишние" системные символы в начале и в конце получившейся строки.
Разберем по шагам, как работает этот алгоритм отсечения:
{"Строка"," состоит ровно из 11 символов. Следовательно, наш полезный текст начинается строго с 12-го символа. Мы отсекаем префикс функцией Сред(стр, 12)."} состоит ровно из 2 символов. Мы отбрасываем их с помощью функции Лев(стр, СтрДлина(стр) - 2).В результате мы получаем готовый программный шаблон:
стр = "Тестовая строка: "" - это кавычка";
// Быстрое системное экранирование
стр = ЗначениеВСтроку(стр);
стр = Сред(стр, 12);
стр = Лев(стр, СтрДлина(стр) - 2);
// Результат в переменной "стр": Тестовая строка: "" - это кавычка
Преимущество метода: Этот способ работает на уровне движка платформы. При обработке очень больших объемов текстовых данных или при массовой обработке строк в циклах этот лайфхак может работать существенно быстрее, чем ручной перебор или многократный вызов функции СтрЗаменить.
При реализации экранирования кавычек обязательно учитывайте следующие важные правила, затронутые участниками дискуссии:
1. Опасность повторной обработки строки
В сообщениях темы прозвучало золотое правило работы с заменой спецсимволов: "главное по этой строке повторно потом не пройтись". Если вы выполняете автозамену кавычек на одной и той же переменной несколько раз (например, при некорректно настроенных циклах или повторном чтении данных), вы полностью разрушите структуру текста. При первом проходе кавычка " превратится в "". При повторном проходе алгоритм найдет уже эти две кавычки и превратит их в четыре """", затем в восемь и так далее. Всегда контролируйте состояние исходной переменной и выполняйте замену только один раз непосредственно перед выводом данных.
2. Заблуждение о "нескольких проходах"
Один из участников высказал мнение, что экранирование кавычек обязательно должно идти в несколько проходов. Это утверждение ошибочно! Встроенная функция СтрЗаменить спроектирована так, что она выполняет замену всех вхождений искомого символа за один проход по строке. Она сканирует текст слева направо, производит замену и сдвигает указатель поиска за пределы вставленного фрагмента, что исключает зацикливание или необходимость повторных вызовов для базовых спецсимволов.
Если в будущем вам придется переносить этот код на современную платформу 1С:Предприятие 8, обязательно обратите внимание на ключевые отличия:
ЗначениеВСтрокуВнутр() выдает строку вида {"S","Текст с ""кавычками"""}. Системный префикс здесь равен 6 символам, а не 11. Использовать этот "хак" в 8-ке категорически не рекомендуется, так как это нарушает стандарты разработки и делает код нечитаемым.Симв() в 1С 8 используется функция Символ(). Соответственно, получение кавычки записывается как Символ(34).СтрЗаменитьПоРегулярномуВыражению().ЗаписьJSON, ЗаписьXML), которые автоматически берут на себя форматирование спецсимволов. Также активно применяются готовые функции Библиотеки Стандартных Подсистем (БСП), например, СтроковыеФункцииКлиентСервер.СократитьДвойныеКавычки для обратной обработки.