При разработке алгоритмов обработки текста в платформе 1С часто возникает вопрос: почему функции Найти() и СтрНайти() не находят вхождение, если буквы в искомой строке и источнике отличаются регистром (например, строчные и заглавные). Разберем, как устроена работа со строками в платформе, всегда ли существовало такое поведение и какими способами можно выполнить поиск без учета регистра символов.
В платформе 1С поведение строковых операций разделено на два принципиально разных механизма:
=. При стандартном сравнении строк (например, в выражении Если Строка1 = Строка2 Тогда) платформа игнорирует регистр символов. Выражение "ТЕКСТ" = "текст" вернет значение Истина.Найти() и СтрНайти(). Встроенные функции поиска выполняют посимвольное бинарное сравнение кодов символов. По этой причине функции Найти() и более современная СтрНайти() всегда были и остаются строго чувствительными к регистру. Никаких встроенных параметров для отключения регистра в этих функциях не предусмотрено.Таким образом, чувствительность к регистру в функциях поиска — это штатное поведение платформы всех версий (начиная с 7.7 и во всех релизах 8.x), а не ошибка конкретного релиза.
Для выполнения регистронезависимого поиска приведем обе строки — как исходный текст, так и искомый образец — к одному регистру с помощью функций ВРег() (верхний регистр) или НРег() (нижний регистр).
Рассмотрим базовый пример:
ГдеИщем = "Номенклатура: Стол письменный";
ЧтоИщем = "стол";
// Поиск с приведением к верхнему регистру
Позиция = СтрНайти(ВРег(ГдеИщем), ВРег(ЧтоИщем));
Если Позиция > 0 Тогда
// Подстрока найдена без учета регистра
КонецЕсли;
Использование ВРег() или НРег() дает абсолютно идентичный результат, выбор конкретной функции является делом привычки разработчика.
Если поиск подстроки выполняется по большому массиву строк, таблице значений или табличной части документа, важно избегать лишних вызовов функций преобразования регистра. Вынесем приведение искомой подстроки к регистру за пределы цикла, чтобы не расходовать процессорное время и оперативную память на повторные вычисления.
Разберем пример оптимизированного обхода таблицы:
ИскомыйОбразец = "комплект";
// Преобразуем образец один раз до начала цикла
ОбразецВРег = ВРег(ИскомыйОбразец);
Для Каждого Стр Из ТаблицаТоваров Цикл
// Внутри цикла преобразуем только проверяемую строку
Если СтрНайти(ВРег(Стр.Наименование), ОбразецВРег) > 0 Тогда
Стр.Выбран = Истина;
КонецЕсли;
КонецЦикла;
Обратим внимание, что функции ВРег() и НРег() изменяют исключительно регистр символов. Они не нормализуют похожие буквы, поэтому символы «е» и «ё» воспринимаются платформой как совершенно разные знаки. Если в прикладной задаче требуется сквозной поиск независимо от написания буквы «ё», предварительно выполним замену через СтрЗаменить():
ТекстНорм = СтрЗаменить(ВРег(ГдеИщем), "Ё", "Е");
ОбразецНорм = СтрЗаменить(ВРег(ЧтоИщем), "Ё", "Е");
Позиция = СтрНайти(ТекстНорм, ОбразецНорм);
В зависимости от архитектурных условий задачи можно использовать и другие инструменты платформы:
ПОДОБНО. В базах данных под управлением MS SQL Server при стандартной настройке сопоставления (_CI_AS — Case Insensitive) поиск через ПОДОБНО "%образец%" по умолчанию не учитывает регистр. Однако для гарантированной кроссплатформенности (в файловых базах и PostgreSQL) рекомендуется также оборачивать поля в функции ВРЕГ() / НРЕГ() прямо в тексте запроса.VBScript.RegExp). Для сложного сопоставления шаблонов в среде Windows можно создать COM-объект регулярных выражений и установить его свойство IgnoreCase = Истина.