Как разделить строку на русские и английские буквы (кириллицу и латиницу) в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

На практике программисты 1С часто сталкиваются с задачей парсинга произвольных строк. Рассмотрим классическую ситуацию: в реквизитах справочника хранятся наименования в формате многоязычного текста, например, «машина // car» или «яблоко // apple». Возникает необходимость вывести или сохранить раздельно строку на русском языке и строку на латинице. Длина наименований у всех элементов разная, поэтому банальное отсечение по фиксированному количеству символов нам не подойдет.

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

Вариант 1. Посимвольный перебор и поиск по строке с алфавитом

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


КириллическиеСимволы = "АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЬьЫыЪъЭэЮюЯя"; 
ЛатинскиеСимволы = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; 

КириллическийТекст = "";
ЛатинскийТекст = "";

Для НомерСимвола = 1 По СтрДлина(ИсходныйТекст) Цикл 
    ТекущийСимвол = Сред(ИсходныйТекст, НомерСимвола, 1); 
    Если СтрНайти(КириллическиеСимволы, ТекущийСимвол) > 0 Тогда 
        КириллическийТекст = КириллическийТекст + ТекущийСимвол; 
    ИначеЕсли СтрНайти(ЛатинскиеСимволы, ТекущийСимвол) > 0 Тогда 
        ЛатинскийТекст = ЛатинскийТекст + ТекущийСимвол; 
    КонецЕсли; 
КонецЦикла;

Важное замечание по оптимизации: В коде выше символы собираются через оператор сложения (конкатенацию). В 1С сложение строк в цикле — это ресурсоемкая операция. Значительно более быстрый и правильный подход — добавлять отфильтрованные символы в объект Массив, а после завершения цикла объединить элементы массива в готовый текст с помощью функции СтрСоединить.

Вариант 2. Использование кодов символов (высокая производительность)

Если нам нужно проанализировать огромные массивы данных, функция СтрНайти внутри цикла может замедлить работу. Выясним причину: поиск подстроки — операция не самая дешевая. Гораздо быстрее работает математическое сравнение кодов символов ASCII. Метод КодСимвола позволяет нам проверить попадание буквы в нужный числовой диапазон.

Латинские (английские) буквы всегда находятся в строгих диапазонах таблицы символов: от 65 до 90 для заглавных (A-Z) и от 97 до 122 для строчных (a-z). Посмотрим, как выглядит оптимизированный цикл проверки на латиницу:


Для Сч = 1 По СтрДлина(ИсходныйТекст) Цикл 
    Код = КодСимвола(Сред(ИсходныйТекст, Сч, 1)); 
    ЭтоЛатиница = ((Код >= 65 И Код <= 90) Или (Код >= 97 И Код <= 122));
    Если ЭтоЛатиница Тогда
        // Обработка латинского символа
    КонецЕсли;
КонецЦикла;

Математическое сравнение чисел (кодов) выполняется на уровне процессора значительно быстрее, чем строковые функции. Этот способ отлично подходит для нагруженных участков кода.

Вариант 3. Использование регулярных выражений (RegExp)

Регулярные выражения — мощнейший инструмент работы со строками, который решает задачу извлечения нужных букв в несколько строк кода. Разберем по шагам, как это можно реализовать. Долгое время разработчикам 1С приходилось использовать COM-объект операционной системы Windows:


RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.MultiLine = Истина; 
RegExp.Global = Истина; 
RegExp.IgnoreCase = Истина; 
RegExp.Pattern = "[a-zA-Z]+"; // Шаблон поиска английских слов

// Далее перебор совпадений...

Однако, COM-объект VBScript.RegExp имеет существенный недостаток: он не будет работать на серверах Linux. К счастью, платформа 1С активно развивается. Начиная с версии платформы 1С:Предприятие 8.3.23, в языке появились встроенные, нативные (кроссплатформенные) регулярные выражения.

Теперь для таких задач можно использовать встроенный объект РегулярноеВыражение и функции СтрНайтиПоРегулярномуВыражению. Применяя паттерн [a-zA-Z]+, мы можем извлечь сразу целые английские слова из текста без циклов перебора символов.

Вариант 4. Готовые функции БСП и хитрые трюки с массивами

Если в вашей конфигурации внедрена Библиотека стандартных подсистем (БСП), нет необходимости «изобретать велосипед». Проанализируем возможности стандартных общих модулей. В модуле СтроковыеФункцииКлиентСервер существуют готовые удобные функции:

  1. ТолькоЛатиницаВСтроке() — проверяет, состоит ли строка только из символов латинского алфавита.
  2. ТолькоКириллицаВСтроке() — аналогично для русского языка.

Для нашей исходной задачи с явными разделителями («машина // car») можно сначала разбить строку в массив функцией СтрРазделить, используя "//" в качестве разделителя, а затем прогнать получившиеся части через эти проверки БСП.

В завершение разберем еще один нестандартный, но лаконичный вариант от участников форума, использующий функции разделения строк и подстановки алфавитов:


КириллическиеСимволы = "АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЬьЫыЪъЭэЮюЯя"; 
ЛатинскиеСимволы = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz"; 

// Удаляем кириллицу (останется латиница и прочие символы)
ЛатинскийТекст = СтрСоединить(СтрРазделить(ИсходныйТекст, КириллическиеСимволы, Ложь), ""); 

// Удаляем латиницу (останется кириллица)
КириллическийТекст = СтрСоединить(СтрРазделить(ИсходныйТекст, ЛатинскиеСимволы, Ложь), "");

В этом примере строка с алфавитом выступает как гигантский набор разделителей. Функция разделяет исходный текст везде, где встречается русская (или английская) буква, а затем мы склеиваем остатки. Это отличный пример гибкости встроенного языка 1С!

← На главную