Почему в 1С не работает регулярное выражение для поиска кириллических слов и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← К списку

Часто при работе с регулярными выражениями в 1С возникает ситуация, когда шаблон, отлично работающий на онлайн-тестерах, отказывается находить совпадения с кириллическими словами. Особенно это касается использования метасимвола границы слова \b. Давайте вместе разберемся, почему так происходит и какие есть способы решить эту задачу.

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

Выясним причину: почему \b не работает с кириллицей?

Чтобы понять корень проблемы, нужно знать, какой механизм (или "движок") регулярных выражений используется в вашей версии платформы 1С. Исторически сложилось так, что подходы менялись, и это напрямую влияет на результат.

  1. Старые версии платформы (до 8.3.23)

    В этих версиях не было встроенной поддержки регулярных выражений. Для работы с ними разработчики обычно использовали внешний COM-объект VBScript.RegExp. Ключевая особенность этого движка в том, что он не полностью поддерживает Unicode. Метасимвол границы слова \b в нем корректно работает только со словами, состоящими из латинских букв [a-zA-Z] и цифр. Кириллические символы он не считает "словесными", поэтому и не может определить границу русского слова.

  2. Современные версии платформы (начиная с 8.3.23)

    Начиная с этой версии, в 1С появилась нативная поддержка регулярных выражений. Она основана на мощной библиотеке ICU (International Components for Unicode). Этот движок полностью поддерживает Unicode, а значит, проблема с определением границ кириллических слов в нем должна быть решена. Однако, чтобы им воспользоваться, необходимо использовать новые встроенные функции языка 1С.

Теперь, когда мы понимаем причины, давайте перейдем к конкретным решениям.

Решение 1: Используем современные функции 1С (для платформы 8.3.23 и новее)

Это самый правильный и рекомендуемый способ для современных конфигураций. Вместо устаревших подходов используем новые встроенные функции, которые работают на движке ICU.

Разберем по шагам, что нужно делать.

  1. Определимся с функцией. В 1С есть несколько функций, и важно выбрать правильную:

    • СтрПодобнаПоРегулярномуВыражению() — проверяет, соответствует ли вся строка целиком шаблону. Часто именно из-за неправильного выбора этой функции возникает ошибка, так как она ищет не вхождение, а полное совпадение.
    • СтрНайтиПоРегулярномуВыражению() — ищет первое вхождение подстроки, соответствующей шаблону. Эта функция подходит для большинства задач по поиску.
    • СтрЗаменитьПоРегулярномуВыражению() — находит и заменяет все вхождения по шаблону.
  2. Составим правильный шаблон. В движке ICU метасимвол \b должен корректно работать с кириллицей. Посмотрим на пример поиска отдельного слова "арка".

    
    ИсходнаяСтрока = "Эта арка была построена давно, аркада вела в сад.";
    Шаблон = "\bарка\b";
    
    // Используем функцию для поиска вхождения
    РезультатПоиска = СтрНайтиПоРегулярномуВыражению(ИсходнаяСтрока, Шаблон);
    
    Если РезультатПоиска <> Неопределено Тогда
        // РезультатПоиска - это объект "РезультатПоискаПоРегулярномуВыражению"
        // Он содержит Позицию и Длину найденного фрагмента
        Сообщить("Слово 'арка' найдено на позиции: " + РезультатПоиска.Позиция);
    Иначе
        Сообщить("Слово 'арка' не найдено.");
    КонецЕсли;
    

    Важный момент: если вы хотите найти слово, но ваша строка содержит еще что-то, не используйте СтрПодобнаПоРегулярномуВыражению. Она вернет Ложь, так как вся строка "Эта арка была..." не равна шаблону "\bарка\b". Эта функция подошла бы, если бы ИсходнаяСтрока была равна просто "арка".

Решение 2: Универсальный шаблон без `\b` с использованием просмотров (lookarounds)

Этот метод подойдет, если вы работаете на старой версии платформы или если по какой-то причине \b в вашей среде все равно ведет себя некорректно. Мы заменим \b на более надежную конструкцию, которая явно указывает, что до и после нашего слова не должно быть других букв.

Для этого воспользуемся так называемыми ретроспективной (lookbehind) и опережающей (lookahead) проверками.

Разберем подробнее, как это работает:

Таким образом, мы вручную создаем аналог "границы слова", который гарантированно будет работать с Unicode.

Посмотрим на пример. Наш шаблон для поиска слова "арка" будет выглядеть так: (?. Он найдет "арка" в строке "эта арка!", но не найдет в слове "аркада".

Давайте посмотрим, как это будет выглядеть в коде для старой платформы с использованием VBScript.RegExp.


// Этот код для старых версий платформы 1С
Попытка
    RegEx = Новый COMОбъект("VBScript.RegExp");
Исключение
    Сообщить("Не удалось создать COM-объект VBScript.RegExp.");
    Возврат;
КонецПопытки;

ИсходнаяСтрока = "Эта арка была построена давно, аркада вела в сад.";

// Указываем, что ищем все вхождения (Global = True)
// и не учитываем регистр (IgnoreCase = True)
RegEx.Global = Истина;
RegEx.IgnoreCase = Истина;
RegEx.Pattern = "(? 0 Тогда
    ПервоеСовпадение = НайденныеСовпадения.Item(0);
    Сообщить("Слово 'арка' найдено на позиции: " + (ПервоеСовпадение.FirstIndex + 1));
Иначе
    Сообщить("Слово 'арка' не найдено.");
КонецЕсли;

Обратите внимание: движок VBScript.RegExp может не поддерживать классы Unicode, такие как \p{L}. В этом случае можно использовать более простое, но менее универсальное выражение, перечислив кириллические символы явно: (?< ← К списку