К статье
Практический материал

Разработка и Конфигурация · 10 мин

Как найти количество слов в строке в 1С

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

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

Главная сложность — не сам подсчёт, а определение того, что считать словом. В тексте встречаются двойные пробелы, табуляции, переносы строк, знаки препинания, и каждый из этих случаев влияет на результат. Ниже разобраны рабочие примеры кода, способы нормализации строки перед подсчётом и критерии проверки корректности результата.

Базовый способ: СтрРазделить по пробелу

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

Функция КоличествоСлов(ИсходнаяСтрока)

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

Возврат МассивСлов.Количество();

КонецФункции

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

Если нужно убрать лишние пробелы ещё до разбиения, используйте СокрЛП() — она удаляет незначащие символы по краям строки. Внутренние двойные пробелы она не трогает, поэтому полагаться только на неё нельзя.

Подготовка строки: пробелы, табуляции и переносы

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

Перед подсчётом приведите все разделители к одному виду — обычному пробелу:

Функция КоличествоСловВТексте(Текст)

ПодготовленныйТекст = СтрЗаменить(Текст, Символы.ВК, " ");

ПодготовленныйТекст = СтрЗаменить(ПодготовленныйТекст, Символы.ПС, " ");

ПодготовленныйТекст = СтрЗаменить(ПодготовленныйТекст, Символы.Таб, " ");

ПодготовленныйТекст = СтрЗаменить(ПодготовленныйТекст, Символ(160), " "); // неразрывный пробел

Возврат СтрРазделить(ПодготовленныйТекст, " ", Ложь).Количество();

КонецФункции

Обратите внимание на неразрывный пробел (символ с кодом 160): он часто попадает в данные при копировании текста из веб-страниц и документов Word. Визуально он неотличим от обычного пробела, но СтрРазделить по обычному пробелу его не учитывает, и два разных слова сливаются в одно.

Порядок действий
  1. 1
    Замените переносы строк (ПС, ВК), табуляции и неразрывные пробелы на обычный пробел
  2. 2
    Выполните СтрРазделить по пробелу с третьим параметром Ложь
  3. 3
    Возьмите Количество() полученного массива
  4. 4
    Проверьте результат на тестовой строке с двойными пробелами и переносами

Подсчёт слов для старых платформ

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

Подсчёт через число вхождений пробела

Если текст гарантированно нормализован (одинарные пробелы, без краевых пробелов), количество слов равно числу пробелов плюс один:

Функция КоличествоСловСтараяПлатформа(Строка)

СтрокаБезКраев = СокрЛП(Строка);

Если ПустаяСтрока(СтрокаБезКраев) Тогда

Возврат 0;

КонецЕсли;

Возврат СтрЧислоВхождений(СтрокаБезКраев, " ") + 1;

КонецФункции

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

Цикл по символам

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

Функция КоличествоСловЦиклом(Строка)

Количество = 0;

ВнутриСлова = Ложь;

Разделители = " " + Символы.Таб + Символы.ПС + Символы.ВК;

Для Позиция = 1 По СтрДлина(Строка) Цикл

Символ = Сред(Строка, Позиция, 1);

Если СтрНайти(Разделители, Символ) > 0 Тогда

ВнутриСлова = Ложь;

ИначеЕсли Не ВнутриСлова Тогда

ВнутриСлова = Истина;

Количество = Количество + 1;

КонецЕсли;

КонецЦикла;

Возврат Количество;

КонецФункции

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

Сравнение вариантов

СтрРазделить с Ложь

Основной способ для платформы 8.3.6 и новее. Короткий код, устойчив к повторным пробелам, но требует предварительной замены переносов и табуляций.

СтрЧислоВхождений + 1

Самый быстрый вариант, но корректен только на нормализованной строке без двойных пробелов. Подходит для контролируемых данных.

Цикл по символам

Работает на любой версии платформы и с любым набором разделителей. Кода больше, на очень длинных текстах медленнее встроенных функций.

Что считать словом: знаки препинания и дефисы

Результат подсчёта напрямую зависит от принятого определения слова. Строка «санкт-петербург, россия» при разбиении по пробелу даст два слова, но «санкт-петербург» — это одно слово или два? А «россия» с запятой — слово «россия» или «россия,»? Для большинства прикладных задач (проверка длины наименования, ограничение текста объявления) достаточно разбиения по пробельным символам, и знаки препинания внутри токена допустимы.

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

Производительность на больших текстах

Для строк размером в несколько страниц любой из описанных способов отрабатывает мгновенно. Проблемы начинаются при обработке сотен тысяч строк в цикле — например, при массовой проверке наименований в справочнике или разборе большого текстового файла.

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

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

При разборе CSV-подобных строк не путайте подсчёт слов с подсчётом полей: там разделитель — точка с запятой или запятая, а пустые поля значимы. Для полей используйте СтрРазделить с включением пустых строк (параметр Истина или опущен), иначе сдвинутся позиции колонок.
ПЗ
Практическое замечание

Проверка корректности и типичные ошибки

Проверяйте функцию на контрольных примерах: пустая строка должна дать 0; строка из одних пробелов — 0; «один» — 1; «раз два» с двойным пробелом — 2; текст с переносом строки между словами — 2. Если хотя бы один случай даёт неожиданное число, ищите проблему в подготовке строки.

Типичные ошибки
01
Вызов СтрРазделить без третьего параметра: двойные пробелы порождают пустые элементы, и счётчик завышается
02
Отсутствие замены переносов строк: слова на стыке строк склеиваются, результат занижается
03
Игнорирование неразрывного пробела (код 160) в текстах, скопированных из Word или браузера
04
Проверка ПустаяСтрока() до СокрЛП: строка из пробелов считается непустой и даёт ложное слово
05
Подсчёт слов через цикл по символам там, где достаточно СтрРазделить: лишний код и потеря скорости на больших данных
Контрольные точки

Как проверить результат

Пустая строка и строка из пробелов
Норма

Функция возвращает 0

Тревожный признак

Возвращается 1 или больше

Строка с двойными и тройными пробелами
Норма

Число равно количеству видимых слов

Тревожный признак

Результат больше числа видимых слов

Текст с переносами строк и табуляцией
Норма

Слова по обе стороны переноса считаются раздельно

Тревожный признак

Слова на стыке строк сливаются в одно

FAQ

Как посчитать количество слов в многострочном текстовом поле формы?

Возьмите значение поля в переменную, замените Символы.ПС, Символы.ВК и Символы.Таб на пробел, затем примените СтрРазделить с параметром Ложь и верните размер массива. Если подсчёт нужен «на лету» при вводе, вызывайте функцию в обработчике ПриИзменении, но для длинных текстов делайте это на сервере или с задержкой, чтобы не тормозить ввод.

Можно ли посчитать слова прямо в запросе 1С?

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

Как учесть дефис: «северо-запад» — одно слово или два?

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

Почему СтрРазделить возвращает больше элементов, чем слов в строке?

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

Как посчитать не слова, а уникальные слова в строке?

Разбейте строку через СтрРазделить, приведите каждое слово к нижнему регистру через НРег() и поместите в Соответствие как ключ — дубликаты перезапишутся. Количество уникальных слов равно размеру соответствия. Дополнительно очищайте слова от знаков препинания, иначе «слово» и «слово,» будут посчитаны разными.

Работает ли СтрРазделить в тонком и веб-клиенте?

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

Итог

Что важно запомнить

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