Очистка строк в 1С: пробелы, спецсимволы, регэкспы

· 9 мин

Содержание

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

Чаще всего строку в 1С нужно очистить перед сравнением или поиском: визуально два значения одинаковы, а равенство не срабатывает — виноват невидимый символ на конце. Ниже — рабочие функции под каждую такую задачу, с кодом, который можно скопировать и сразу вставить в модуль.

Какими функциями 1С работает со строками

Весь арсенал очистки строится на горстке встроенных функций. Они есть на любом клиенте и сервере, COM-компоненты не требуются.

ФункцияЧто делает
СокрЛП(Стр)убирает пробелы слева и справа
СокрЛ(Стр) / СокрП(Стр)обрезает пробелы только слева / только справа
СтрЗаменить(Стр, Что, Чем)заменяет все вхождения подстроки
СтрНайти(Стр, Подстрока)позиция вхождения, 0 если нет
СтрДлина(Стр)длина строки
Сред(Стр, Нач, Длина)подстрока с позиции
КодСимвола(Стр, Поз)код символа в позиции
Символ(Код)символ по коду
СтрНачинаетсяС / СтрЗаканчиваетсяНапроверка префикса / суффикса

СокрЛП обрезает только обычные пробелы (код 32) по краям. Табуляцию, перенос строки и неразрывный пробел внутри текста он не трогает — их снимают отдельно через СтрЗаменить.

Для «невидимых» символов удобно системное перечисление Символы:

Символы.ПС   // перевод строки, код 10
Символы.ВК   // возврат каретки, код 13
Символы.Таб  // табуляция, код 9
Символы.НПП  // неразрывный пробел, код 160

Как убрать пробелы: по краям, двойные и неразрывные

Начнём с самого частого — лишних пробелов.

Пробелы по краям. Одна функция закрывает задачу:

Результат = СокрЛП(Строка);

Двойные и тройные пробелы внутри сводим к одному. Заменяем два пробела на один, пока в строке остаются сдвоенные:

Пока СтрНайти(Строка, "  ") > 0 Цикл
    Строка = СтрЗаменить(Строка, "  ", " ");
КонецЦикла;
Строка = СокрЛП(Строка);

Цикл нужен именно потому, что СтрЗаменить за один проход превратит четыре пробела подряд в два, а не в один — повторяем, пока сдвоенных не останется.

Все пробелы без исключения (например, из телефона или ИНН) убираем заменой на пустую строку:

Строка = СтрЗаменить(Строка, " ", "");

Неразрывный пробел — тот самый, из-за которого СокрЛП «не работает ». Его часто приносят данные, скопированные с сайтов и из Excel. Код символа — 160, в перечислении это Символы.НПП:

Строка = СтрЗаменить(Строка, Символы.НПП, " ");
Строка = СокрЛП(Строка);

Если после СокрЛП строка всё ещё «с хвостом» — почти всегда это неразрывный пробел или табуляция. Сначала замените их на обычный пробел, потом обрезайте.

Удаляем переносы строк, табуляцию и спецсимволы

Текст из многострочного поля или из выгрузки нередко содержит переносы и табуляцию. Схлопнуть их в один пробел можно пачкой замен:

Строка = СтрЗаменить(Строка, Символы.ПС, " ");  // перевод строки
Строка = СтрЗаменить(Строка, Символы.ВК, " ");  // возврат каретки
Строка = СтрЗаменить(Строка, Символы.Таб, " "); // табуляция
Строка = СтрЗаменить(Строка, Символы.НПП, " "); // неразрывный пробел

Пока СтрНайти(Строка, "  ") > 0 Цикл
    Строка = СтрЗаменить(Строка, "  ", " ");
КонецЦикла;
Строка = СокрЛП(Строка);

Порядок важен: сначала превращаем все спецсимволы в пробелы, затем схлопываем сдвоенные пробелы и только в конце обрезаем края.

Убрать конкретные символы — те же замены на пустую строку. Например, выкинуть точки, запятые и дефисы из кода:

Для Каждого Симв Из СтрРазделить(".,-/\", "") Цикл
    Строка = СтрЗаменить(Строка, Симв, "");
КонецЦикла;

Здесь СтрРазделить(".,-/\", "") с пустым разделителем возвращает массив отдельных символов — удобно перечислить «мусор» в одной строке и пройти по нему циклом.

Как оставить в строке только цифры или только буквы

Для телефонов, ИНН, СНИЛС и артикулов нужен обратный подход: не удалять мусор, а оставить только нужное. Перебираем символы и собираем результат по кодам.

Только цифры (коды 48–57):

Функция ТолькоЦифры(Знач Строка) Экспорт
    Результат = "";
    Для Позиция = 1 По СтрДлина(Строка) Цикл
        Код = КодСимвола(Строка, Позиция);
        Если Код >= 48 И Код <= 57 Тогда
            Результат = Результат + Символ(Код);
        КонецЕсли;
    КонецЦикла;
    Возврат Результат;
КонецФункции

Вызов ТолькоЦифры("+7 (900) 123-45-67") вернёт 79001234567.

Только цифры и латинские буквы (для артикулов и серийных номеров) — добавляем диапазоны кодов латиницы (65–90 и 97–122):

Функция ТолькоБуквыИЦифры(Знач Строка) Экспорт
    Результат = "";
    Для Позиция = 1 По СтрДлина(Строка) Цикл
        Код = КодСимвола(Строка, Позиция);
        ЭтоЦифра  = (Код >= 48 И Код <= 57);
        ЭтоЛатБ   = (Код >= 65 И Код <= 90) Или (Код >= 97 И Код <= 122);
        Если ЭтоЦифра Или ЭтоЛатБ Тогда
            Результат = Результат + Символ(Код);
        КонецЕсли;
    КонецЦикла;
    Возврат Результат;
КонецФункции

Перебор по кодам предсказуем и работает одинаково на Windows и Linux, в тонком и веб-клиенте. Для кириллицы диапазоны кодов шире и зависят от раскладки — если нужны русские буквы, надёжнее проверять символ через поиск в «белом списке» допустимых символов, а не по номерам кодов.

Регулярные выражения: есть ли они в 1С и чем заменить

Встроенного движка регулярных выражений в языке 1С:Предприятия нет. То, что в других языках делается одним Pattern, здесь собирают из СтрЗаменить, СтрНайти и перебора символов — как в примерах выше.

Когда без регэкспа совсем неудобно и база работает на Windows, можно подключить внешний COM-объект движка скриптов:

РегВыр = Новый COMОбъект("VBScript.RegExp");
РегВыр.Global = Истина;
РегВыр.Pattern = "[^0-9]";          // всё, кроме цифр
Результат = РегВыр.Replace(Строка, ""); // удалить

Шаблон [^0-9] означает «любой символ, кроме цифры», а Replace с пустой заменой их вычищает — получается тот же «только цифры», но одной строкой. Для схлопывания любых пробельных символов в один пробел пригодится шаблон \s+:

РегВыр.Pattern = "\s+";                   // любые пробелы, табы, переносы подряд
Строка = СокрЛП(РегВыр.Replace(Строка, " "));

COM-объект VBScript.RegExp — это Windows-компонент. На сервере под Linux, в веб-клиенте и в мобильном приложении он недоступен и вызовет ошибку. Если база хоть иногда работает не на Windows, используйте переборные функции из разделов выше, а не регулярные выражения.

Для большинства задач очистки регэксп избыточен: убрать пробелы, переносы и оставить цифры дешевле и переносимее штатными функциями.

Невидимые символы из буфера обмена и выгрузок

Самый коварный мусор — тот, что не видно. Он приезжает, когда значение скопировали из Excel, с сайта, из письма или получили через обмен данными.

Типичные «невидимки»:

  • 🔸 неразрывный пробел (код 160) — выглядит как пробел, но СокрЛП его не берёт;
  • 🔸 табуляция (код 9) — между «колонками» при копировании из таблицы;
  • 🔸 переносы строки и возврат каретки (коды 10 и 13) — в конце многострочных полей;
  • 🔸 неразрывный дефис и «длинное тире» — вместо обычного минуса в кодах и артикулах.

Как понять, что в строке невидимый символ: сравните СтрДлина(Строка) до и после СокрЛП. Если длина не изменилась, а «хвост» на вид есть — проверьте код последнего символа:

Если СтрДлина(Строка) > 0 Тогда
    Сообщить("Код последнего символа: "
        + КодСимвола(Строка, СтрДлина(Строка)));
КонецЕсли;

Код 160 — неразрывный пробел, 9 — табуляция, 10 или 13 — перенос. Дальше чистите нужной заменой. Эта же проверка объясняет классическую загадку «строки одинаковые, а условие Строка1 = Строка2 ложно»: в одной из них прячется лишний символ.

Снести разом все управляющие символы (коды 0–31: табуляция, переносы, служебные байты из выгрузок) можно одним перебором — оставляем всё, у чего код не ниже 32:

Функция БезУправляющихСимволов(Знач Строка) Экспорт
    Результат = "";
    Для Позиция = 1 По СтрДлина(Строка) Цикл
        Код = КодСимвола(Строка, Позиция);
        Если Код >= 32 Тогда
            Результат = Результат + Символ(Код);
        КонецЕсли;
    КонецЦикла;
    Возврат Результат;
КонецФункции

Неразрывный пробел (код 160) эта функция не тронет — он выше порога 32, поэтому его по-прежнему снимают отдельной заменой Символы.НПП.

Готовая функция: универсальный очиститель строки

Собираем всё в одну функцию общего модуля. Она снимает невидимые символы, схлопывает пробелы и обрезает края — то, что нужно перед сравнением, поиском и записью в реквизит:

Функция ОчищеннаяСтрока(Знач Строка) Экспорт
    Строка = СтрЗаменить(Строка, Символы.НПП, " ");
    Строка = СтрЗаменить(Строка, Символы.Таб, " ");
    Строка = СтрЗаменить(Строка, Символы.ПС,  " ");
    Строка = СтрЗаменить(Строка, Символы.ВК,  " ");

    Пока СтрНайти(Строка, "  ") > 0 Цикл
        Строка = СтрЗаменить(Строка, "  ", " ");
    КонецЦикла;

    Возврат СокрЛП(Строка);
КонецФункции

Параметр объявлен через Знач — функция меняет локальную копию и не портит переданную переменную.

Нужно снять в начале лишний префикс (номер, символ №) — пригодится связка СтрНачинаетсяС и Сред:

Если СтрНачинаетсяС(Строка, "№") Тогда
    Строка = Сред(Строка, 2); // со второго символа до конца
КонецЕсли;

Три базовые заготовки на каждый день:

  • 🔹 очистить от пробелов по краям — СокрЛП(Строка);
  • 🔹 свести к одному пробелу и снять невидимки — функция ОчищеннаяСтрока выше;
  • 🔹 оставить только цифры — функция ТолькоЦифры.

Регистр при очистке и сравнении строк

Отдельная ловушка — регистр. СтрЗаменить и СтрНайти различают большие и маленькие буквы: замена "АБВ" не тронет "абв". Поэтому «ООО Ромашка» и «ооо ромашка» для 1С — разные строки, даже после снятия пробелов.

Перед сравнением регистр приводят к единому. Три функции:

ВРег("ромашка")  // РОМАШКА — всё в верхний регистр
НРег("РОМАШКА")  // ромашка — всё в нижний
ТРег("ромашка")  // Ромашка — первая буква каждого слова заглавная

Надёжный шаблон сравнения двух строк без оглядки на пробелы и регистр — очистить обе функцией ОчищеннаяСтрока, привести к одному регистру и только потом сравнивать:

Функция СтрокиРавны(Знач Строка1, Знач Строка2) Экспорт
    Строка1 = ВРег(ОчищеннаяСтрока(Строка1));
    Строка2 = ВРег(ОчищеннаяСтрока(Строка2));
    Возврат Строка1 = Строка2;
КонецФункции

ВРег и НРег работают и с кириллицей, и с латиницей. Для поиска без учёта регистра приведите к одному регистру и строку, и искомую подстроку: СтрНайти(ВРег(Текст), ВРег(Образец)).

Проверьте себя
Что делает `СокрЛП(" текст ")`?
Какой код у неразрывного пробела?
Чем убрать все пробелы внутри строки?

Частые вопросы

Чем `СокрЛП` отличается от `СтрЗаменить(Строка, " ", "")`?
СокрЛП обрезает пробелы только по краям строки, внутренние остаются. СтрЗаменить с пустой заменой убирает все пробелы, включая те, что внутри слов — так чистят телефоны и коды, но не обычный текст.
Почему `СокрЛП` не убирает пробел в конце строки?
Значит, это не обычный пробел (код 32), а неразрывный (код 160) или табуляция (код 9). Сначала замените Символы.НПП и Символы.Таб на обычный пробел, потом применяйте СокрЛП.
Есть ли в 1С регулярные выражения из коробки?
Встроенного движка нет. На Windows можно подключить COM-объект VBScript.RegExp, но он не работает на сервере под Linux и в веб-клиенте. Переносимее собирать очистку из СтрЗаменить и перебора по КодСимвола.
Как очистить (удалить) строку таблицы значений, а не текст?
Это другая задача: у таблицы значений ТаблицаЗначений.Удалить(СтрокаТЗ) убирает одну строку, а ТаблицаЗначений.Очистить() — сразу все строки. К очистке текстового значения эти методы отношения не имеют.
Строки на вид одинаковые, а равенство не срабатывает — почему?
Почти всегда в одной из строк есть невидимый символ по краям: неразрывный пробел, табуляция или перенос. Пропустите обе строки через функцию очистки перед сравнением — и условие заработает.