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

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

Как разбить строку по словам в 1С

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

Задача разбить строку по словам возникает в 1С постоянно: при разборе ФИО на фамилию, имя и отчество, при обработке адресов, при парсинге данных из файлов и при разборе пользовательского ввода. Встроенный язык 1С предлагает несколько инструментов для этого, и выбор зависит от версии платформы и структуры исходной строки.

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

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

Разбиение строки функцией СтрРазделить

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

Строка = "Иванов Иван Иванович";

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

Для Каждого Слово Из МассивСлов Цикл

Сообщить(Слово);

КонецЦикла;

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

Разделителем может быть не только одиночный символ, но и строка из нескольких символов, а также набор разделителей. Например, СтрРазделить(Строка, " ,;", Ложь) разобьёт строку одновременно по пробелам, запятым и точкам с запятой — каждый символ из второго параметра трактуется как самостоятельный разделитель.

1c
МассивСлов = СтрРазделить("Иванов  Иван   Иванович", " ", Ложь); // 3 элемента, пустые отброшены

Разбор ФИО и строк с переменным числом пробелов

Типовой сценарий — разбор ФИО, введённого одной строкой. Проблема в том, что пользователи вводят данные небрежно: лишние пробелы в начале и конце, двойные пробелы между словами, иногда табуляции. Перед разбиением строку стоит нормализовать.

ФИО = СокрЛП(СтрокаФИО);

// Заменяем табуляции на пробелы

ФИО = СтрЗаменить(ФИО, Символы.Таб, " ");

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

Если МассивСлов.Количество() >= 3 Тогда

Фамилия = МассивСлов[0];

Имя = МассивСлов[1];

Отчество = МассивСлов[2];

ИначеЕсли МассивСлов.Количество() = 2 Тогда

Фамилия = МассивСлов[0];

Имя = МассивСлов[1];

Иначе

ВызватьИсключение "Не удалось разобрать ФИО";

КонецЕсли;

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

Двойные фамилии и составные имена («Салтыков-Щедрин», «Анна-Мария») функция разбиения не испортит — дефис не является разделителем. Но фамилии с пробелом внутри (например, «ван дер Берг») разобьются на лишние элементы, и автоматический разбор даст неверный результат. Для таких данных нужна отдельная логика или ручная корректировка.

Разбиение в старых версиях платформы

В платформах ниже 8.3.6 функции СтрРазделить() нет. Классическая замена — цикл с поиском разделителя через СтрНайти() (в старых версиях — Найти()) и отсечением найденной части.

Функция РазбитьСтроку(Знач Строка, Разделитель)

Результат = Новый Массив;

Строка = Строка + Разделитель;

Позиция = Найти(Строка, Разделитель);

Пока Позиция > 0 Цикл

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

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

Результат.Добавить(Слово);

КонецЕсли;

Строка = Сред(Строка, Позиция + СтрДлина(Разделитель));

Позиция = Найти(Строка, Разделитель);

КонецЦикла;

Возврат Результат;

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

Трюк с добавлением разделителя в конец строки избавляет от отдельной обработки последнего слова: цикл гарантированно найдёт завершающий разделитель и выйдет корректно. Проверка ПустаяСтрока() отсекает пустые элементы при повторных пробелах — аналог третьего параметра СтрРазделить().

Разбор через многострочные строки

Ещё один приём для старых версий — заменить пробелы на перевод строки и использовать СтрПолучитьСтроку() и СтрЧислоСтрок(). Способ рабочий, но уступает циклу по читаемости и требует предварительной очистки от пустых строк, если пробелов несколько.

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

Для Номер = 1 По СтрЧислоСтрок(Текст) Цикл

Слово = СтрПолучитьСтроку(Текст, Номер);

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

// обработка слова

КонецЕсли;

КонецЦикла;

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

СтрРазделить()

Штатный способ для платформы 8.3.6 и выше. Короткий код, контроль пустых элементов. Не работает в старых версиях.

Цикл со СтрНайти()

Универсален для любых версий, полный контроль над логикой. Больше кода, легче допустить ошибку в смещении позиции.

СтрПолучитьСтроку()

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

Выбор разделителя и обработка сложных случаев

Слова в реальных данных разделяются не только пробелами. В адресах встречаются запятые, в данных из Excel — точки с запятой, в текстах — переносы строк. Если разделителей несколько, есть два подхода: передать набор символов-разделителей в СтрРазделить() или предварительно свести все разделители к одному через СтрЗаменить().

// Вариант 1: несколько разделителей сразу

МассивСлов = СтрРазделить(Строка, " ,;" + Символы.ПС, Ложь);

// Вариант 2: нормализация перед разбиением

Норм = СтрЗаменить(Строка, ",", " ");

Норм = СтрЗаменить(Норм, ";", " ");

МассивСлов = СтрРазделить(Норм, " ", Ложь);

Первый вариант короче, но второй предпочтительнее, когда разделитель многосимвольный: например, строка разделяется последовательностью «||» или « — ». В СтрРазделить() набор символов трактуется как перечень одиночных разделителей, а не как одна последовательность, поэтому для многосимвольного разделителя работает только замена или цикл с СтрНайти().

Отдельный случай — строки, где разделитель встречается внутри данных, например CSV с полями в кавычках: "Иванов, Иван";35;"Москва, Арбат". Простое разбиение по разделителю здесь разрушит структуру. Такие форматы разбирают посимвольным парсером с отслеживанием открытых кавычек или штатными средствами чтения текста.

Проверка результата разбиения

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

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

Сообщить("Элементов: " + МассивСлов.Количество());

Для Инд = 0 По МассивСлов.ВГраница() Цикл

Сообщить("[" + Инд + "] = '" + МассивСлов[Инд] + "'");

КонецЦикла;

Обрамление значения апострофами в выводе помогает увидеть скрытые пробелы и непечатаемые символы, которые визуально незаметны, но ломают сравнение строк дальше по коду. Если слово «не находится» в массиве через Найти(), хотя визуально присутствует, почти всегда дело в лишнем пробеле или неразрывном пробеле (символ 160), который попадает в данные при копировании из Word или веб-страниц.

Неразрывный пробел функция СокрЛП() не удаляет, и СтрРазделить() по обычному пробелу его не учитывает. Перед разбором данных из внешних источников заменяйте его явно: СтрЗаменить(Строка, Символ(160), " ").

Контрольные точки

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

Количество элементов массива
Норма

Совпадает с ожидаемым числом слов

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

Элементов больше — вероятно, пустые строки от двойных пробелов (параметр Ложь не передан)

Содержимое элементов в отладчике
Норма

Слова без пробелов по краям

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

Лишние пробелы или неразрывный пробел (символ 160) внутри значений

Поиск слова в массиве
Норма

МассивСлов.Найти(Слово) возвращает индекс

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

Возвращает Неопределено при визуально совпадающем значении — скрытые символы

Типичные ошибки и производительность

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

По производительности: СтрРазделить() работает быстро и подходит для пакетной обработки больших объёмов. А вот ручная конкатенация строк в цикле при обратной сборке (Результат = Результат + Слово на тысячах итераций) заметно медленнее, чем сборка через массив с последующим СтрСоединить(). Для обратной операции — склейки массива слов в строку — всегда используйте СтрСоединить(МассивСлов, " ").

Типичные ошибки
01
Не передан третий параметр Ложь — двойные пробелы дают пустые элементы и смещают индексы ФИО
02
Обращение к МассивСлов[2] без проверки Количество() — ошибка «Индекс за границами» на неполных данных
03
Разбор CSV с кавычками простым СтрРазделить — запятые внутри полей разрушают структуру
04
Игнорирование неразрывного пробела (символ 160) в данных из Word и веба — слова не разделяются
05
Склейка строк конкатенацией в цикле вместо СтрСоединить — лишняя нагрузка на больших объёмах
Порядок действий
  1. 1
    Очистите строку: СокрЛП(), замена табуляций и неразрывных пробелов на обычные пробелы
  2. 2
    Разбейте строку: МассивСлов = СтрРазделить(Строка, " ", Ложь)
  3. 3
    Проверьте МассивСлов.Количество() перед обращением к элементам по индексу
  4. 4
    Извлеките нужные слова и при необходимости соберите результат обратно через СтрСоединить()
  5. 5
    Протестируйте на граничных случаях: пустая строка, одно слово, двойные пробелы

Частые вопросы

Чем разбить строку по словам в 1С 8.2 или 8.3 младше 8.3.6?

Функции СтрРазделить в этих версиях нет. Используйте цикл с Найти() и отсечением подстрок через Лев() и Сред(), либо замените пробелы на перевод строки и пройдитесь по результату функциями СтрЧислоСтрок() и СтрПолучитьСтроку(). Оба приёма приведены выше с готовым кодом.

Почему в массиве появляются пустые элементы?

Потому что между словами несколько пробелов подряд, а третий параметр СтрРазделить не задан или равен Истина. Передайте Ложь третьим параметром — пустые подстроки будут отброшены, и индексация слов станет предсказуемой.

Как разбить строку, если разделитель состоит из нескольких символов?

СтрРазделить трактует второй параметр как набор одиночных символов-разделителей, поэтому для многосимвольного разделителя он не подходит. Либо замените многосимвольный разделитель на одиночный символ через СтрЗаменить и затем разбейте, либо используйте цикл со СтрНайти с учётом длины разделителя при смещении позиции.

Как собрать массив слов обратно в одну строку?

Используйте функцию СтрСоединить(МассивСлов, " ") — она объединит элементы массива через указанный разделитель. Это быстрее и надёжнее, чем конкатенация в цикле, особенно на больших массивах.

Слово есть в строке, но сравнение и поиск его не находят. В чём причина?

Чаще всего в данных присутствует неразрывный пробел (код символа 160), который попадает из Word, Excel или веб-страниц и визуально неотличим от обычного. Перед разбором выполните СтрЗаменить(Строка, Символ(160), " ") и дополнительно проверьте значения в отладчике, обрамляя их видимыми символами при выводе.

Можно ли разбить строку сразу по нескольким разным разделителям?

Да. Передайте в СтрРазделить строку из всех нужных символов, например СтрРазделить(Строка, " ,;" + Символы.ПС, Ложь) — каждый символ будет работать как самостоятельный разделитель. Помните, что многосимвольные последовательности так задать нельзя.

Итог

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

Используйте СтрРазделить(Строка, " ", Ложь) для разбиения по словам в платформе 8.3.6+, обязательно проверяйте Количество() перед доступом по индексу, очищайте строку от неразрывных пробелов и табуляций, а для сборки обратно применяйте СтрСоединить.