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

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

1С: как найти пробел в строке

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

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

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

Функция Найти(): базовый способ поиска пробела

Функция Найти(Строка, ПодстрокаПоиска) возвращает номер позиции первого вхождения подстроки в строку. Нумерация символов начинается с 1. Если пробел не найден, функция возвращает 0 — это ключевой признак, который используется для проверки наличия пробела.

Пример простейшего поиска:

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

Позиция = Найти(Строка, " ");

Если Позиция > 0 Тогда

Сообщить("Пробел найден на позиции " + Позиция);

Иначе

Сообщить("Пробелов нет");

КонецЕсли;

В данном примере функция вернёт 7 — позицию пробела между фамилией и именем. Функция находит только первое вхождение: если в строке несколько пробелов, остальные нужно искать отдельно.

Функция СтрНайти(): современный вариант с расширенными параметрами

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

Синтаксис: СтрНайти(Строка, ПодстрокаПоиска, НаправлениеПоиска, НачальнаяПозиция, НомерВхождения). Два первых параметра обязательны, остальные опциональны.

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

// Первый пробел

Поз1 = СтрНайти(Строка, " "); // 7

// Второй пробел

Поз2 = СтрНайти(Строка, " ", , , 2); // 12

// Последний пробел — поиск с конца

ПозПосл = СтрНайти(Строка, " ", НаправлениеПоиска.СКонца);

Направление НаправлениеПоиска.СКонца особенно полезно, когда нужно отделить последнее слово в строке — например, выделить отчество из полного ФИО или расширение из имени файла. Без этой функции пришлось бы перебирать строку в цикле от последнего символа к первому.

Маршрут решения

Как выбрать функцию

Платформа ниже 8.3.6 или код должен работать вездеИспользуйте Найти() — она универсальна
Нужен поиск с конца строки или N-е вхождениеИспользуйте СтрНайти() с параметрами НаправлениеПоиска и НомерВхождения
Нужно разбить строку по всем пробеламИспользуйте СтрРазделить() вместо поиска позиций

Проверка наличия пробела в строке

Часто позиция пробела не нужна — требуется лишь узнать, есть он или нет. Например, при проверке, что пользователь ввёл логин без пробелов, или что артикул не содержит лишних символов. Для этого достаточно сравнить результат Найти() с нулём.

Если Найти(Логин, " ") > 0 Тогда

ВызватьИсключение "Логин не должен содержать пробелы";

КонецЕсли;

Отдельный случай — проверка на пробелы в начале и конце строки. Для этого удобнее сравнить строку с результатом функции СокрЛП(): если они не равны, значит, по краям есть пробелы или другие незначащие символы (табуляция, перевод строки).

Если Строка <> СокрЛП(Строка) Тогда

Сообщить("Есть пробелы в начале или в конце строки");

КонецЕсли;

Поиск всех пробелов и разбор строки на части

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

Классический цикл с Найти() требует обрезки строки после каждого найденного пробела и накопления смещения. Это громоздко и легко приводит к ошибкам в индексах. С СтрРазделить() задача решается одной строкой:

Части = СтрРазделить("Иванов Иван Иванович", " ");

Фамилия = Части[0]; // "Иванов"

Имя = Части[1]; // "Иван"

Отчество = Части[2]; // "Иванович"

Функция возвращает массив подстрок. По умолчанию пустые части (при двойных пробелах) включаются в результат — если они не нужны, передайте вторым параметром Ложь: СтрРазделить(Строка, " ", Ложь). Это важно при обработке «грязных» данных из внешних источников, где между словами может стоять несколько пробелов.

Разбор ФИО на части
  1. 1
    Очистите строку: Строка = СокрЛП(Строка)
  2. 2
    Разбейте: Части = СтрРазделить(Строка, " ", Ложь)
  3. 3
    Проверьте количество элементов: Части.Количество() должно быть не меньше ожидаемого
  4. 4
    Извлеките элементы по индексам: Части[0], Части[1], Части[2]
  5. 5
    Обработайте случаи, когда частей меньше трёх — не обращайтесь к несуществующим индексам

Неразрывный пробел и другие невидимые символы

Частая причина «неработающего» поиска — в строке стоит не обычный пробел (код 32), а неразрывный пробел (код 160). Такие символы регулярно попадают в данные при копировании из веб-страниц, Word или при выгрузках из других систем. Визуально они неотличимы, но Найти(Строка, " ") их не находит.

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

НПП = Символ(160); // неразрывный пробел

Позиция = Найти(Строка, НПП);

Надёжная практика — перед разбором строки заменить все неразрывные пробелы на обычные: Строка = СтрЗаменить(Строка, Символ(160), " "). Аналогично могут встречаться табуляция (Символы.Таб) и символы перевода строки (Символы.ПС, Символы.ВК) — для них действует тот же приём.

Типичные ошибки
01
Поиск обычного пробела там, где стоит неразрывный (код 160) — результат 0 при визуально видимом пробеле
02
Обращение к Части[2] без проверки Части.Количество() — ошибка «Индекс находится за границами массива»
03
Ожидание, что Найти() найдёт все пробелы — она возвращает только первое вхождение
04
Сравнение результата Найти() с Неопределено вместо 0 — проверка никогда не сработает
05
Забытое СокрЛП() перед разбором — пустые элементы массива при пробелах по краям

Практические приёмы и ограничения

Несколько полезных приёмов, которые часто используются вместе с поиском пробела. Подсчёт количества пробелов в строке без цикла: СтрЧислоВхождений(Строка, " ") — функция доступна с платформы 8.3.6. Извлечение первого слова: Лев(Строка, Найти(Строка, " ") - 1), но только после проверки, что пробел вообще есть, иначе получите строку нулевой длины или ошибку логики.

Извлечение текста после последнего пробела удобно делать через СтрНайти() с поиском с конца:

Поз = СтрНайти(Строка, " ", НаправлениеПоиска.СКонца);

Если Поз > 0 Тогда

ПоследнееСлово = Сред(Строка, Поз + 1);

КонецЕсли;

Ограничение, о котором стоит помнить: строковые функции 1С не поддерживают регулярные выражения. Если нужно искать «любой пробельный символ» или сложный шаблон, придётся либо перебирать символы в цикле с проверкой кодов, либо использовать внешние компоненты. Для большинства учётных задач достаточно предварительной нормализации строки через СтрЗаменить().

Итог

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

Найти(Строка, " ") возвращает позицию первого пробела или 0. СтрНайти() добавляет поиск с конца и по номеру вхождения, СтрРазделить() разбивает строку по всем пробелам сразу. Перед разбором нормализуйте строку: замените неразрывные пробелы и примените СокрЛП().

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

Что возвращает Найти(), если пробела в строке нет?

Функция возвращает число 0. Поэтому проверка наличия пробела выглядит как Найти(Строка, " ") > 0. Сравнивать результат с Неопределено или пустой строкой нельзя — такая проверка всегда будет ложной.

Как найти последний пробел в строке?

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

Почему Найти() не находит пробел, хотя он виден на экране?

Скорее всего, в строке неразрывный пробел (код символа 160) или табуляция. Перед поиском выполните Строка = СтрЗаменить(Строка, Символ(160), " ") — это приведёт невидимые разделители к обычному пробелу.

Как посчитать количество пробелов в строке?

На платформе 8.3.6+ используйте СтрЧислоВхождений(Строка, " "). Альтернатива для старых версий — вычислить разность длин исходной строки и строки после СтрЗаменить(Строка, " ", ""), либо взять СтрРазделить(Строка, " ").Количество() минус 1.

Чем СтрНайти() лучше Найти()?

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

Как проверить, что строка состоит только из пробелов?

Примените СокрЛП(Строка) и сравните результат с пустой строкой: Если СокрЛП(Строка) = "" Тогда. Функция удалит все пробельные символы по краям, и если ничего не осталось — значит, содержательных данных в строке нет.