В практике разработчика 1С часто возникает задача обработки текстовых данных. Одной из классических задач является подсчет количества слов в строке, которые могут быть разделены произвольным количеством пробелов. На первый взгляд задача кажется тривиальной, но при детальном рассмотрении выясняется множество нюансов, связанных с производительностью, чистотой кода и корректностью обработки спецсимволов. В этой статье мы разберем как «архаичные» оригинальные методы, так и современные стандарты платформы.
Рассмотрим нестандартный подход, который часто встречается в старых архивах форумов. Код выглядит как сложная вложенная конструкция функций СтрЗаменить. Давайте проанализируем, как работает эта строка:
Слов = СтрЧислоВхождений(СтрЗаменить(СтрЗаменить(СокрЛП(Стр), " ", "ЭтаПрабэл"), "таПрабэлЭ", ""), "ЭтаПрабэл") + 1;
Выясним причину, по которой этот код справляется с неограниченным количеством пробелов между словами. Разберем процесс по шагам, используя воображаемую строку "Привет мир" (два пробела между словами):
СокрЛП(Стр): Удаляет лишние пробелы в начале и в конце строки, чтобы они не влияли на итоговый результат."ЭтаПрабэл". Если между словами было два пробела, мы получим: "ПриветЭтаПрабэлЭтаПрабэлмир"."таПрабэлЭ" и заменяем ее на пустую строку. Посмотрим внимательно: на стыке двух меток "ЭтаПрабэл" и "ЭтаПрабэл" образуется последовательность букв "...таПрабэлЭтаПрабэл...". Если мы удалим кусок "таПрабэлЭ" из середины этого «паровозика», то от двух меток останется только одна (первая буква Э от первой метки и хвост таПрабэл от второй)."ЭтаПрабэл".СтрЧислоВхождений считает количество оставшихся меток, а прибавление единицы дает нам количество слов (так как разделителей всегда на один меньше, чем объектов).Проанализируем ситуацию: этот метод является примером «блистательного, но опасного мышления». Он имитирует работу регулярных выражений, которых долгое время не было в стандартном функционале 1С. Однако у него есть критический недостаток. Если в тексте встретится слово, содержащее комбинацию букв из нашей метки (например, имя «Эдуард» или слово «Этап»), алгоритм может сработать некорректно и выдать ошибочный результат.
Начиная с версии платформы 8.3.6, разработчикам доступен гораздо более элегантный и производительный инструмент. Рассмотрим подробнее функцию СтрРазделить. Она позволяет разбивать строку в массив по разделителю, и, что самое важное, имеет встроенный механизм обработки пустых строк.
Посмотрим на пример правильного кода:
МассивСлов = СтрРазделить(ИсходнаяСтрока, " ", Ложь);
КоличествоСлов = МассивСлов.Количество();
Разберем параметры этой функции:
" ").Ложь. Оно указывает системе, что пустые подстроки (которые образуются, если между словами стоит несколько пробелов подряд) включать в итоговый массив не нужно.Этот метод работает значительно быстрее, код читается мгновенно, и в нем нет «магических» текстовых констант, которые могут случайно встретиться в данных пользователя.
Зачастую текст попадает в 1С из внешних источников (Excel, веб-сайты, почта). В таких строках вместо обычного пробела (код 32) часто встречается неразрывный пробел (код 160). Обычные функции поиска пробела его «не видят».
Для надежного подсчета слов проанализируем предварительную очистку строки:
// Заменяем неразрывные пробелы на обычные
ТекстДляОбработки = СтрЗаменить(ИсходнаяСтрока, Символы.НПП, " ");
// Заменяем табуляцию на пробелы
ТекстДляОбработки = СтрЗаменить(ТекстДляОбработки, Символы.Таб, " ");
// Теперь можно считать
МассивСлов = СтрРазделить(СокрЛП(ТекстДляОбработки), " ", Ложь);
Результат = МассивСлов.Количество();
Такой подход гарантирует, что визуально разделенные слова будут посчитаны правильно, даже если они разделены знаками табуляции или неразрывными пробелами.
До появления СтрРазделить в среде разработчиков был популярен метод с использованием объекта СписокЗначений. Рассмотрим его для понимания исторического контекста или работы на старых версиях платформы:
Стр = СтрЗаменить(СокрЛП(ИсходнаяСтрока), " ", Символы.ПС);
Список = Новый СписокЗначений;
Список.ИзСтроки(Стр);
// Удаляем пустые элементы, если пробелов было много
Индекс = Список.Количество() - 1;
Пока Индекс >= 0 Цикл
Если ПустаяСтрока(Список[Индекс].Значение) Тогда
Список.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
КоличествоСлов = Список.Количество();
Метод ИзСтроки превращает многострочный текст в элементы списка. Мы заменяем пробелы на символы переноса строки (Символы.ПС), после чего получаем список «слов». Однако, в отличие от СтрРазделить, этот метод требует ручного удаления пустых строк в цикле, что делает его менее эффективным.
Подведем итог нашему анализу. Выбор метода зависит от версии платформы и требований к точности:
СтрРазделить(Строка, " ", Ложь). Это стандарт индустрии."Мама, мыла раму!" должна вернуть 3 слова, а не 4 (запятая как слово), предварительно очищайте строку от знаков препинания с помощью СтрЗаменить."ЭтаПрабэл", хороши для разминки ума и понимания работы алгоритмов замены, но в промышленном коде они создают риски трудноуловимых ошибок.Совместное использование предварительной очистки (удаление лишних символов и замена спецпробелов) и функции СтрРазделить — это наиболее надежный и профессиональный способ решения задачи подсчета слов в 1С.