Разработка и Конфигурация · 10 мин
Как найти количество слов в строке в 1С
Как посчитать количество слов в строке в 1С: разбор по разделителям, функции СтрРазделить, готовые примеры кода, обработка пробелов, переносов и типичные ошибки.
Во встроенном языке 1С нет готовой функции «количество слов», поэтому задачу решают через разбиение строки по разделителям. Самый надёжный способ — функция СтрРазделить(), которая превращает строку в массив подстрок, а количество слов определяется как размер этого массива. Для старых платформ, где функция недоступна, применяют перебор с СтрПолучитьСтроку() или ручной цикл по символам.
Главная сложность — не сам подсчёт, а определение того, что считать словом. В тексте встречаются двойные пробелы, табуляции, переносы строк, знаки препинания, и каждый из этих случаев влияет на результат. Ниже разобраны рабочие примеры кода, способы нормализации строки перед подсчётом и критерии проверки корректности результата.
Базовый способ: СтрРазделить по пробелу
Функция СтрРазделить() доступна в платформе начиная с версии 8.3.6 и работает как на сервере, так и на клиенте, включая тонкий и веб-клиент. Она принимает исходную строку, разделитель и необязательный признак включения пустых строк.
Функция КоличествоСлов(ИсходнаяСтрока)
МассивСлов = СтрРазделить(ИсходнаяСтрока, " ", Ложь);
Возврат МассивСлов.Количество();
КонецФункции
Третий параметр, равный Ложь, критически важен: он убирает пустые элементы, которые возникают при нескольких пробелах подряд. Без него строка «раз два» (два пробела) даст три элемента вместо двух слов. Пробелы в начале и конце строки при этом тоже отбрасываются автоматически.
Если нужно убрать лишние пробелы ещё до разбиения, используйте СокрЛП() — она удаляет незначащие символы по краям строки. Внутренние двойные пробелы она не трогает, поэтому полагаться только на неё нельзя.
Подготовка строки: пробелы, табуляции и переносы
Реальные тексты из многострочных полей, файлов и документов содержат переносы строк (Символы.ПС, Символы.ВК) и табуляции (Символы.Таб). Если разбивать такую строку только по пробелу, слова на стыке строк склеятся: «конец\nначало» будет посчитано как одно слово.
Перед подсчётом приведите все разделители к одному виду — обычному пробелу:
Функция КоличествоСловВТексте(Текст)
ПодготовленныйТекст = СтрЗаменить(Текст, Символы.ВК, " ");
ПодготовленныйТекст = СтрЗаменить(ПодготовленныйТекст, Символы.ПС, " ");
ПодготовленныйТекст = СтрЗаменить(ПодготовленныйТекст, Символы.Таб, " ");
ПодготовленныйТекст = СтрЗаменить(ПодготовленныйТекст, Символ(160), " "); // неразрывный пробел
Возврат СтрРазделить(ПодготовленныйТекст, " ", Ложь).Количество();
КонецФункции
Обратите внимание на неразрывный пробел (символ с кодом 160): он часто попадает в данные при копировании текста из веб-страниц и документов Word. Визуально он неотличим от обычного пробела, но СтрРазделить по обычному пробелу его не учитывает, и два разных слова сливаются в одно.
- 1Замените переносы строк (ПС, ВК), табуляции и неразрывные пробелы на обычный пробел
- 2Выполните СтрРазделить по пробелу с третьим параметром Ложь
- 3Возьмите Количество() полученного массива
- 4Проверьте результат на тестовой строке с двойными пробелами и переносами
Подсчёт слов для старых платформ
На платформах ниже 8.3.6 функции СтрРазделить нет. Там применяют либо перебор через СтрЧислоВхождений(), либо цикл по символам с отслеживанием границ слов.
Подсчёт через число вхождений пробела
Если текст гарантированно нормализован (одинарные пробелы, без краевых пробелов), количество слов равно числу пробелов плюс один:
Функция КоличествоСловСтараяПлатформа(Строка)
СтрокаБезКраев = СокрЛП(Строка);
Если ПустаяСтрока(СтрокаБезКраев) Тогда
Возврат 0;
КонецЕсли;
Возврат СтрЧислоВхождений(СтрокаБезКраев, " ") + 1;
КонецФункции
Способ быстрый, но требователен к качеству строки: любой двойной пробел завышает результат. Используйте его только когда данные проходят предварительную очистку.
Цикл по символам
Универсальный вариант, не зависящий от версии платформы и устойчивый к любым разделителям:
Функция КоличествоСловЦиклом(Строка)
Количество = 0;
ВнутриСлова = Ложь;
Разделители = " " + Символы.Таб + Символы.ПС + Символы.ВК;
Для Позиция = 1 По СтрДлина(Строка) Цикл
Символ = Сред(Строка, Позиция, 1);
Если СтрНайти(Разделители, Символ) > 0 Тогда
ВнутриСлова = Ложь;
ИначеЕсли Не ВнутриСлова Тогда
ВнутриСлова = Истина;
Количество = Количество + 1;
КонецЕсли;
КонецЦикла;
Возврат Количество;
КонецФункции
Логика проста: слово засчитывается в момент перехода от разделителя к не-разделителю. Такой подход легко расширить, добавив в строку разделителей знаки препинания, если по требованиям задачи они тоже должны разделять слова.
Сравнение вариантов
Основной способ для платформы 8.3.6 и новее. Короткий код, устойчив к повторным пробелам, но требует предварительной замены переносов и табуляций.
Самый быстрый вариант, но корректен только на нормализованной строке без двойных пробелов. Подходит для контролируемых данных.
Работает на любой версии платформы и с любым набором разделителей. Кода больше, на очень длинных текстах медленнее встроенных функций.
Что считать словом: знаки препинания и дефисы
Результат подсчёта напрямую зависит от принятого определения слова. Строка «санкт-петербург, россия» при разбиении по пробелу даст два слова, но «санкт-петербург» — это одно слово или два? А «россия» с запятой — слово «россия» или «россия,»? Для большинства прикладных задач (проверка длины наименования, ограничение текста объявления) достаточно разбиения по пробельным символам, и знаки препинания внутри токена допустимы.
Если требуется «лингвистический» подсчёт, после разбиения нужно очищать каждый элемент от знаков препинания и отбрасывать пустые остатки. Учтите, что полноценного анализа с учётом переносов и составных слов встроенными средствами 1С не получить — для таких задач обычно согласовывают упрощённые правила с заказчиком и фиксируют их в требованиях.
Производительность на больших текстах
Для строк размером в несколько страниц любой из описанных способов отрабатывает мгновенно. Проблемы начинаются при обработке сотен тысяч строк в цикле — например, при массовой проверке наименований в справочнике или разборе большого текстового файла.
Практические рекомендации: выполняйте подсчёт на сервере, а не в клиентском цикле; не вызывайте функцию внутри запроса — в языке запросов 1С нет аналога, поэтому сначала выгрузите данные, затем обработайте. Если строка нужна только для подсчёта, не сохраняйте промежуточный массив слов в переменные, которые живут дольше необходимого, — на очень больших объёмах это влияет на потребление памяти.
Для циклической обработки предпочтителен СтрРазделить: встроенные функции платформы работают заметно быстрее интерпретируемого цикла по символам.
При разборе CSV-подобных строк не путайте подсчёт слов с подсчётом полей: там разделитель — точка с запятой или запятая, а пустые поля значимы. Для полей используйте СтрРазделить с включением пустых строк (параметр Истина или опущен), иначе сдвинутся позиции колонок.
Проверка корректности и типичные ошибки
Проверяйте функцию на контрольных примерах: пустая строка должна дать 0; строка из одних пробелов — 0; «один» — 1; «раз два» с двойным пробелом — 2; текст с переносом строки между словами — 2. Если хотя бы один случай даёт неожиданное число, ищите проблему в подготовке строки.
Как проверить результат
Функция возвращает 0
Возвращается 1 или больше
Число равно количеству видимых слов
Результат больше числа видимых слов
Слова по обе стороны переноса считаются раздельно
Слова на стыке строк сливаются в одно
FAQ
Как посчитать количество слов в многострочном текстовом поле формы?
Возьмите значение поля в переменную, замените Символы.ПС, Символы.ВК и Символы.Таб на пробел, затем примените СтрРазделить с параметром Ложь и верните размер массива. Если подсчёт нужен «на лету» при вводе, вызывайте функцию в обработчике ПриИзменении, но для длинных текстов делайте это на сервере или с задержкой, чтобы не тормозить ввод.
Можно ли посчитать слова прямо в запросе 1С?
Нет, в языке запросов нет функций разбиения строк или подсчёта слов. Стандартный путь — выбрать строки запросом, затем обработать их в цикле на встроенном языке. Для отбора по критерию «не более N слов» иногда применяют косвенные условия через ПОДОБНО, но это ненадёжно и не рекомендуется.
Как учесть дефис: «северо-запад» — одно слово или два?
При разбиении по пробелам это одно слово, что соответствует большинству прикладных задач. Если по требованиям дефис должен разделять, добавьте его в список заменяемых символов перед СтрРазделить. Правило нужно согласовать с постановщиком задачи, потому что для фамилий и географических названий разные правила дают разный результат.
Почему СтрРазделить возвращает больше элементов, чем слов в строке?
Почти всегда причина в том, что не передан третий параметр Ложь: тогда повторные пробелы создают пустые элементы массива. Вторая частая причина — разделитель из нескольких символов воспринимается как единая последовательность, а не набор. Проверьте вызов и выведите массив в цикле, чтобы увидеть лишние элементы.
Как посчитать не слова, а уникальные слова в строке?
Разбейте строку через СтрРазделить, приведите каждое слово к нижнему регистру через НРег() и поместите в Соответствие как ключ — дубликаты перезапишутся. Количество уникальных слов равно размеру соответствия. Дополнительно очищайте слова от знаков препинания, иначе «слово» и «слово,» будут посчитаны разными.
Работает ли СтрРазделить в тонком и веб-клиенте?
Да, функция доступна во всех клиентах начиная с платформы 8.3.6, включая тонкий и веб-клиент, и не требует вызова сервера. Однако при обработке больших объёмов данных в цикле предпочтительнее выполнять код на сервере, чтобы не перегружать клиентское соединение.
Что важно запомнить
Количество слов в строке 1С считают через СтрРазделить с параметром Ложь, предварительно заменив переносы строк, табуляции и неразрывные пробелы на обычный пробел. Для старых платформ используют СтрЧислоВхождений или цикл по символам. Результат всегда проверяйте на строках с двойными пробелами, переносами и пустым значением.