Как в 1С откусить часть строки до определенного символа или переноса строки

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Проблема поиска невидимых символов

Зачастую стандартная функция Найти() не срабатывает, если разделителем выступает не просто пробел, а управляющий символ (например, «¶», перевод строки LF или возврат каретки CR). Это происходит потому, что визуальное отображение символа в отладчике или текстовом редакторе может не совпадать с его реальным внутренним кодом. Проанализируем ситуацию: если мы пытаемся найти символ «в лоб», копируя его из текста, платформа может его не распознать из-за различий в кодировках.

Рассмотрим первый способ решения — поиск по коду символа:

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


// Исходная строка с неявным символом переноса
ИсходнаяСтрока = "180803-09¶ ¶ This message was created automatically.";

// Предположим, мы выяснили, что код символа равен 182 или 13
КодРазделителя = 182; 
Позиция = Найти(ИсходнаяСтрока, Симв(КодРазделителя));

Если Позиция > 0 Тогда
    Результат = Лев(ИсходнаяСтрока, Позиция - 1);
    Сообщить("Найденный номер: " + Результат);
КонецЕсли;

Использование системного перечисления «Символы»

В платформе 1С существует более элегантный и универсальный способ работы со спецсимволами, о котором часто забывают. Вместо того чтобы гадать, какой код у переноса строки (10 или 13), лучше использовать глобальный контекст Символы. Это делает код читаемым и кроссплатформенным.

Проанализируем основные свойства этого объекта:

Если ваша строка содержит визуальный перенос, попробуйте следующий вариант:


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

Если Позиция > 0 Тогда
    НужныйНомер = СокрЛП(Лев(ИсходнаяСтрока, Позиция - 1));
КонецЕсли;

Метод фильтрации через «разрешенные символы»

Иногда структура строки нестабильна: после номера может идти пробел, точка с запятой или сразу несколько разных спецсимволов. В этом случае надежнее использовать метод «белого списка», то есть перебирать строку посимвольно до тех пор, пока нам встречаются допустимые знаки (цифры, дефисы, буквы).

Разберем по шагам алгоритм, предложенный участниками сообщества:

  1. Определяем строку, содержащую все символы, которые могут входить в состав номера.
  2. Запускаем цикл от первого символа до конца строки.
  3. Проверяем каждый символ функцией Найти() внутри нашего «белого списка».
  4. Как только встречается символ, не входящий в список, прерываем цикл.

Посмотрим на программную реализацию этого метода:


ИсходнаяСтрока = "180803-09¶ ¶ This message was created automatically.";
// Указываем все возможные знаки, которые могут быть в номере
РазрешенныеСимволы = "0123456789-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/"; 
НужныйНомер = "";

Для й = 1 По СтрДлина(ИсходнаяСтрока) Цикл
    ОчереднойСимвол = Сред(ИсходнаяСтрока, й, 1);
    
    // Если символ не найден в списке разрешенных - это наш разделитель
    Если Найти(РазрешенныеСимволы, ОчереднойСимвол) = 0 Тогда
        Прервать;
    КонецЕсли;
    
    НужныйНомер = НужныйНомер + ОчереднойСимвол;
КонецЦикла;

Сообщить("Результат обработки: " + НужныйНомер);

Важное замечание: этот метод очень гибкий, так как позволяет игнорировать любые «дрянные» символы, независимо от их кода. Однако помните, что для очень длинных строк (сотни тысяч символов) посимвольный перебор может работать медленнее, чем встроенные строковые функции.

Современный подход: функция СтрРазделить

Если вы работаете на платформе версии 8.3.6 и выше, наиболее эффективным и лаконичным способом будет использование функции СтрРазделить(). Она позволяет разбить строку в массив, используя разделитель, и нам останется просто взять первый элемент этого массива.

Выясним, как это работает на практике:


// В качестве разделителя передаем спецсимвол переноса строки
МассивЧастей = СтрРазделить(ИсходнаяСтрока, Символы.ПС, Ложь);

// Первый элемент массива и будет нашим номером
Если МассивЧастей.Количество() > 0 Тогда
    НужныйНомер = СокрЛП(МассивЧастей[0]);
КонецЕсли;

Преимущество этого метода в том, что если разделитель не будет найден, функция вернет массив с одним элементом, содержащим всю исходную строку, и код не вызовет ошибку.

Рекомендации по производительности

Проанализируем, какой метод выбрать в зависимости от условий задачи:

  1. Если вы точно знаете символ-разделитель, используйте СтрРазделить() или комбинацию Найти() + Лев(). Это самые быстрые операции, реализованные на уровне ядра платформы.
  2. Если разделителей может быть несколько (например, пробел, табуляция и перенос строки), СтрРазделить() позволяет передать строку, где каждый символ будет считаться разделителем.
  3. Если структура номера сложная и заранее неизвестна, используйте цикл с фильтрацией по РазрешенныеСимволы, но старайтесь ограничивать длину просматриваемой строки.
  4. Для удаления лишних невидимых символов по краям результата всегда используйте функцию СокрЛП().

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

← На главную