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

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

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

Разбор «магического» алгоритма с двойной заменой

Рассмотрим нестандартный подход, который часто встречается в старых архивах форумов. Код выглядит как сложная вложенная конструкция функций СтрЗаменить. Давайте проанализируем, как работает эта строка:


Слов = СтрЧислоВхождений(СтрЗаменить(СтрЗаменить(СокрЛП(Стр), " ", "ЭтаПрабэл"), "таПрабэлЭ", ""), "ЭтаПрабэл") + 1;

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

  1. Функция СокрЛП(Стр): Удаляет лишние пробелы в начале и в конце строки, чтобы они не влияли на итоговый результат.
  2. Первая замена (внутренняя): Мы заменяем каждый одиночный пробел на длинную уникальную строку-метку "ЭтаПрабэл". Если между словами было два пробела, мы получим: "ПриветЭтаПрабэлЭтаПрабэлмир".
  3. Вторая замена (внешняя): Здесь кроется главная хитрость. Мы ищем подстроку "таПрабэлЭ" и заменяем ее на пустую строку. Посмотрим внимательно: на стыке двух меток "ЭтаПрабэл" и "ЭтаПрабэл" образуется последовательность букв "...таПрабэлЭтаПрабэл...". Если мы удалим кусок "таПрабэлЭ" из середины этого «паровозика», то от двух меток останется только одна (первая буква Э от первой метки и хвост таПрабэл от второй).
  4. Результат: Сколько бы пробелов ни шло подряд, после второй замены они все «схлопнутся» в одну метку "ЭтаПрабэл".
  5. Подсчет: Функция СтрЧислоВхождений считает количество оставшихся меток, а прибавление единицы дает нам количество слов (так как разделителей всегда на один меньше, чем объектов).

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

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

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

Посмотрим на пример правильного кода:


МассивСлов = СтрРазделить(ИсходнаяСтрока, " ", Ложь);
КоличествоСлов = МассивСлов.Количество();

Разберем параметры этой функции:

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

Обработка неразрывных пробелов и спецсимволов

Зачастую текст попадает в 1С из внешних источников (Excel, веб-сайты, почта). В таких строках вместо обычного пробела (код 32) часто встречается неразрывный пробел (код 160). Обычные функции поиска пробела его «не видят».

Для надежного подсчета слов проанализируем предварительную очистку строки:


// Заменяем неразрывные пробелы на обычные
ТекстДляОбработки = СтрЗаменить(ИсходнаяСтрока, Символы.НПП, " ");
// Заменяем табуляцию на пробелы
ТекстДляОбработки = СтрЗаменить(ТекстДляОбработки, Символы.Таб, " ");
// Теперь можно считать
МассивСлов = СтрРазделить(СокрЛП(ТекстДляОбработки), " ", Ложь);
Результат = МассивСлов.Количество();

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

Альтернативный метод через СписокЗначений

До появления СтрРазделить в среде разработчиков был популярен метод с использованием объекта СписокЗначений. Рассмотрим его для понимания исторического контекста или работы на старых версиях платформы:


Стр = СтрЗаменить(СокрЛП(ИсходнаяСтрока), " ", Символы.ПС);
Список = Новый СписокЗначений;
Список.ИзСтроки(Стр);
// Удаляем пустые элементы, если пробелов было много
Индекс = Список.Количество() - 1;
Пока Индекс >= 0 Цикл
    Если ПустаяСтрока(Список[Индекс].Значение) Тогда
        Список.Удалить(Индекс);
    КонецЕсли;
    Индекс = Индекс - 1;
КонецЦикла;
КоличествоСлов = Список.Количество();

Метод ИзСтроки превращает многострочный текст в элементы списка. Мы заменяем пробелы на символы переноса строки (Символы.ПС), после чего получаем список «слов». Однако, в отличие от СтрРазделить, этот метод требует ручного удаления пустых строк в цикле, что делает его менее эффективным.

Рекомендации по выбору решения

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

  1. Для версии 8.3.6 и выше: Всегда используйте СтрРазделить(Строка, " ", Ложь). Это стандарт индустрии.
  2. Если нужно учитывать знаки препинания: Если строка вида "Мама, мыла раму!" должна вернуть 3 слова, а не 4 (запятая как слово), предварительно очищайте строку от знаков препинания с помощью СтрЗаменить.
  3. Избегайте «говнокода»: Методы, подобные "ЭтаПрабэл", хороши для разминки ума и понимания работы алгоритмов замены, но в промышленном коде они создают риски трудноуловимых ошибок.

Совместное использование предварительной очистки (удаление лишних символов и замена спецпробелов) и функции СтрРазделить — это наиболее надежный и профессиональный способ решения задачи подсчета слов в 1С.

← На главную