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

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

При обработке текстовых реквизитов, входящих номеров документов или строковых выгрузок часто возникает необходимость извлечь определенную часть строки. Типичный сценарий: строка содержит два составных документа с номерами и датами, например "Пр.Пр. № 0000-000003 от 28.02.2015 № 294-о от 19.02.2015", а нам требуется отсечь первую часть и оставить только вторую, начиная со второго символа «№».

Разберем по шагам различные способы решения этой задачи на встроенном языке 1С:Предприятие, проанализируем их плюсы, минусы и потенциальные подводные камни при работе с данными.

Способ 1. Использование встроенной функции СтрНайти (платформа 8.3.6 и выше)

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

Если нам гарантированно нужно получить срез именно со второго знака номера, передадим число 2 в пятый параметр функции (НомерВхождения):


ИсходнаяСтрока = "Пр.Пр. № 0000-000003 от 28.02.2015 № 294-о от 19.02.2015";
Позиция = СтрНайти(ИсходнаяСтрока, "№", , , 2);

Если Позиция > 0 Тогда
    Результат = Сред(ИсходнаяСтрока, Позиция);
Иначе
    Результат = "";
КонецЕсли;

Проанализируем важный нюанс: обратите внимание на обязательную проверку Позиция > 0. Если в строке окажется меньше двух символов номера, функция СтрНайти вернет 0. Если мы сразу передадим ноль в функцию Сред(ИсходнаяСтрока, 0), платформа интерпретирует 0 как 1 и вернет строку целиком без изменений. Поэтому проверка условия обязательна для предотвращения некорректной обработки данных.

Если же логика задачи требует отрезать строку по последнему номеру (даже если знаков номера встретится три или больше), используем поиск с конца строки через параметр НаправлениеПоиска:


Позиция = СтрНайти(ИсходнаяСтрока, "№", НаправлениеПоиска.СКонца);
Результат = ?(Позиция > 0, Сред(ИсходнаяСтрока, Позиция), "");

Этот способ является наиболее производительным: поиск выполняется за один проход, без создания временных массивов и лишнего расхода оперативной памяти.

Способ 2. Решение для устаревших платформ (8.2, 8.3.5 и режим совместимости)

Если конфигурация работает в режиме совместимости с версиями ниже 8.3.6, функция СтрНайти недоступна и вызовет ошибку компиляции. В этом случае мы используем базовую функцию Найти в два последовательных шага:

  1. Находим индекс первого знака «№».
  2. Выполняем поиск второго вхождения в остатке строки, начиная со следующей позиции.
  3. Складываем найденные смещения и отсекаем нужный хвост строки функцией Сред.

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


ИсходнаяСтрока = "Пр.Пр. № 0000-000003 от 28.02.2015 № 294-о от 19.02.2015";

ПерваяПозиция = Найти(ИсходнаяСтрока, "№");
Если ПерваяПозиция > 0 Тогда
    ХвостСтроки = Сред(ИсходнаяСтрока, ПерваяПозиция + 1);
    ВтораяПозицияВХвосте = Найти(ХвостСтроки, "№");
    
    Если ВтораяПозицияВХвосте > 0 Тогда
        ИтоговаяПозиция = ПерваяПозиция + ВтораяПозицияВХвосте;
        Результат = Сред(ИсходнаяСтрока, ИтоговаяПозиция);
    Иначе
        Результат = "";
    КонецЕсли;
Иначе
    Результат = "";
КонецЕсли;

Такой код работает на любой версии платформы 1С:Предприятие 8, включая толстый и тонкий клиенты, а также внешние соединения.

Способ 3. Подмена разделителя на перевод строки

В обсуждении предложен быстрый однострочный вариант с заменой искомого символа на знак переноса строки Символы.ПС и получением нужной строки через СтрПолучитьСтроку:


ИсходнаяСтрока = "Пр.Пр. № 0000-000003 от 28.02.2015 № 294-о от 19.02.2015";
Результат = "№" + СтрПолучитьСтроку(СтрЗаменить(ИсходнаяСтрока, "№", Символы.ПС), 2);

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

Способ 4. Разложение строки в массив

Еще один популярный подход — разделить строку по разделителю на части. Для этого можно применить встроенную функцию СтрРазделить или метод из Библиотеки стандартных подсистем (БСП) СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок.

Рассмотрим реализацию через СтрРазделить:


ИсходнаяСтрока = "Пр.Пр. № 0000-000003 от 28.02.2015 № 294-о от 19.02.2015";
МассивЧастей = СтрРазделить(ИсходнаяСтрока, "№", Ложь);

Если МассивЧастей.Количество() >= 3 Тогда
    // Индекс 0: "Пр.Пр. "
    // Индекс 1: " 0000-000003 от 28.02.2015 "
    // Индекс 2: " 294-о от 19.02.2015"
    Результат = "№" + МассивЧастей[2];
Иначе
    Результат = "";
КонецЕсли;

Обратите внимание на особенности этого механизма:

  1. Функция СтрРазделить полностью удаляет указанный символ-разделитель из элементов массива, поэтому знак «№» необходимо конкатенировать обратно вручную.
  2. Если исходная строка не начиналась с разделителя, первой частью (с индексом 0) будет текст до первого вхождения. Таким образом, фрагмент после второго знака номера окажется под индексом 2.

Способ 5. Использование регулярных выражений

Начиная с версии платформы 8.3.23, в 1С появились встроенные методы работы с регулярными выражениями (стандарт ICU): СтрНайтиПоРегулярномуВыражению и СтрРазделитьПоРегулярномуВыражению. Они позволяют гибко вырезать текст по сложному шаблону (например, проверять, что после номера идут именно цифры и дата).

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

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

Резюме и рекомендации

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

← На главную