Разработка и Конфигурация · 12 мин
Как разбить строку по словам в 1С
Разбираем, как разбить строку по словам в 1С: функции СтрРазделить, СтрПолучитьСтроку, работа с пробелами и разделителями, примеры кода и типичные ошибки.
Задача разбить строку по словам возникает в 1С постоянно: при разборе ФИО на фамилию, имя и отчество, при обработке адресов, при парсинге данных из файлов и при разборе пользовательского ввода. Встроенный язык 1С предлагает несколько инструментов для этого, и выбор зависит от версии платформы и структуры исходной строки.
Основная функция современных версий платформы — СтрРазделить(), которая возвращает массив подстрок по указанному разделителю. Для старых конфигураций и особых случаев применяются СтрПолучитьСтроку(), циклический поиск через СтрНайти() и работа с многострочными строками. Каждый способ имеет свои ограничения: поведение с пустыми элементами, обработку нескольких пробелов подряд и производительность на больших объёмах.
Ниже разобраны рабочие варианты кода, условия выбора между ними, проверка результата и типичные ошибки, из-за которых разбор строки даёт неожиданный результат.
Разбиение строки функцией СтрРазделить
Функция СтрРазделить() доступна в платформе 1С:Предприятие 8.3.6 и выше. Она принимает исходную строку, разделитель и необязательный флаг включения пустых строк, а возвращает массив подстрок. Для разбиения по словам разделителем служит пробел.
Строка = "Иванов Иван Иванович";
МассивСлов = СтрРазделить(Строка, " ", Ложь);
Для Каждого Слово Из МассивСлов Цикл
Сообщить(Слово);
КонецЦикла;
Третий параметр имеет ключевое значение. Если передать Истина (или опустить параметр — по умолчанию пустые строки включаются), то при двух пробелах подряд между ними в массив попадёт пустой элемент. Для разбора ФИО или адресов, где количество пробелов не нормировано, это приводит к смещению индексов и ошибкам логики. Передавайте Ложь, чтобы пустые элементы отбрасывались.
Разделителем может быть не только одиночный символ, но и строка из нескольких символов, а также набор разделителей. Например, СтрРазделить(Строка, " ,;", Ложь) разобьёт строку одновременно по пробелам, запятым и точкам с запятой — каждый символ из второго параметра трактуется как самостоятельный разделитель.
МассивСлов = СтрРазделить("Иванов Иван Иванович", " ", Ложь); // 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) внутри значений
МассивСлов.Найти(Слово) возвращает индекс
Возвращает Неопределено при визуально совпадающем значении — скрытые символы
Типичные ошибки и производительность
Большинство проблем при разбиении строк связаны не с самой функцией, а с качеством входных данных и невнимательностью к граничным случаям. Пустая исходная строка, строка из одних пробелов, отсутствие ожидаемого слова — всё это нужно обрабатывать явно.
По производительности: СтрРазделить() работает быстро и подходит для пакетной обработки больших объёмов. А вот ручная конкатенация строк в цикле при обратной сборке (Результат = Результат + Слово на тысячах итераций) заметно медленнее, чем сборка через массив с последующим СтрСоединить(). Для обратной операции — склейки массива слов в строку — всегда используйте СтрСоединить(МассивСлов, " ").
- 1Очистите строку: СокрЛП(), замена табуляций и неразрывных пробелов на обычные пробелы
- 2Разбейте строку: МассивСлов = СтрРазделить(Строка, " ", Ложь)
- 3Проверьте МассивСлов.Количество() перед обращением к элементам по индексу
- 4Извлеките нужные слова и при необходимости соберите результат обратно через СтрСоединить()
- 5Протестируйте на граничных случаях: пустая строка, одно слово, двойные пробелы
Частые вопросы
Чем разбить строку по словам в 1С 8.2 или 8.3 младше 8.3.6?
Функции СтрРазделить в этих версиях нет. Используйте цикл с Найти() и отсечением подстрок через Лев() и Сред(), либо замените пробелы на перевод строки и пройдитесь по результату функциями СтрЧислоСтрок() и СтрПолучитьСтроку(). Оба приёма приведены выше с готовым кодом.
Почему в массиве появляются пустые элементы?
Потому что между словами несколько пробелов подряд, а третий параметр СтрРазделить не задан или равен Истина. Передайте Ложь третьим параметром — пустые подстроки будут отброшены, и индексация слов станет предсказуемой.
Как разбить строку, если разделитель состоит из нескольких символов?
СтрРазделить трактует второй параметр как набор одиночных символов-разделителей, поэтому для многосимвольного разделителя он не подходит. Либо замените многосимвольный разделитель на одиночный символ через СтрЗаменить и затем разбейте, либо используйте цикл со СтрНайти с учётом длины разделителя при смещении позиции.
Как собрать массив слов обратно в одну строку?
Используйте функцию СтрСоединить(МассивСлов, " ") — она объединит элементы массива через указанный разделитель. Это быстрее и надёжнее, чем конкатенация в цикле, особенно на больших массивах.
Слово есть в строке, но сравнение и поиск его не находят. В чём причина?
Чаще всего в данных присутствует неразрывный пробел (код символа 160), который попадает из Word, Excel или веб-страниц и визуально неотличим от обычного. Перед разбором выполните СтрЗаменить(Строка, Символ(160), " ") и дополнительно проверьте значения в отладчике, обрамляя их видимыми символами при выводе.
Можно ли разбить строку сразу по нескольким разным разделителям?
Да. Передайте в СтрРазделить строку из всех нужных символов, например СтрРазделить(Строка, " ,;" + Символы.ПС, Ложь) — каждый символ будет работать как самостоятельный разделитель. Помните, что многосимвольные последовательности так задать нельзя.
Что важно запомнить
Используйте СтрРазделить(Строка, " ", Ложь) для разбиения по словам в платформе 8.3.6+, обязательно проверяйте Количество() перед доступом по индексу, очищайте строку от неразрывных пробелов и табуляций, а для сборки обратно применяйте СтрСоединить.