Внешняя компонента для выполнения регулярных выражений

Программирование - Внешние компоненты

Регулярные выражения RegEx

44
Внешняя Native API компонента для выполнения регулярных выражений на платформе 1С:Предприятие 8. Написана на C++. Используется движок из стандартной библиотеки шаблонов C++11 - std::regex.

Внимание! Текущая версия является тестовой и еще не была протестирована на реальных проектах и базах. 

Текущая версия собрана для следующих платформ:
Windows 32bit 
Windows 64bit 
Linux 32bit 
Linux 64bit

MacOS 64bit 

Тестировалось на платформе 8.3.12.1567 (Windows XP SP3, Windows 7, Windows Server 2008 R2, Ubuntu 14 32-64bit, MacOS Sierra 10.12)

Адрес open-source проекта на GitHub: https://github.com/alexkmbk/RegEx1CAddin

Бинарные файлы можно скачать также с GitHub: https://github.com/alexkmbk/RegEx1CAddin/releases

Архив содержит скомпилированный набор компонент, предназначенный для загрузки в общий макет конфигурации.

Сборка осуществлялась с использованием следующих инструментов:

Под Windows: Microsoft Visual Studio Community 2017

Под Linux: GCC 6

Под Mac OS: Clang 9

Использовалась статическая сборка, поэтому компонента не требует установки каких-либо дополнительных библиотек.

Компонента реализует следующие методы:

Метод НайтиСовпадения / Matches(<Текст для анализа>, <Регулярное выражение>).

Метод выполняет поиск в переданном тексте по переданному регулярному выражению.

Результатом выполнения метода будет массив результатов поиска. Каждый элемент массива - найденная подгруппа поиска. Если подгрупп нет, то массив будет содержать один элемент - найденную строку.

Возвращаемое значение: Ничего не возвращает.

Для того, чтобы получить результаты выполнения метода (массив результатов), необходимо выполнить метод Следующий/Next(), и после этого, в свойстве ТекущееЗначение/CurrentValue будет доступно значение текущей подгруппы результата выполнения (текущий элемент массива результатов). Идея  похожа на обход результата запроса.

Пример:

Рег.НайтиСовпадения("Hello world", "([A-Za-z]+)\s+([a-z]+)");

Пока Рег.Следующий() Цикл
    Сообщить(Рег.ТекущееЗначение);    
КонецЦикла; 

Результат будет содержать 3 элемента:

Hello world
Hello
world

Метод Количество/Count()

Возвращает количество результатов поиска, после выполнения метода НайтиСовпадения / Matches

Метод Заменить/Replace(<Текст для анализа>, <Регулярное выражение>, <Значение для замены>).

Заменяет в переданном тексте часть, соответствующую регулярному выражению, значением, переданным третьим параметром.

Возвращаемое значение: Строка, результат замены.

Метод Совпадает/IsMatch(<Текст для анализа>, <Регулярное выражение>).

Делает проверку на соответствие текста регулярному выражению.

Возвращаемое значение: Булево. Возвращает значение Истина если текст соответствует регулярному выражению.

Пример использования:

Предполагается что архив с компонентами был загружен в общий макет "RegEx"

УстановитьВнешнююКомпоненту("ОбщийМакет.RegEx");
ПодключитьВнешнююКомпоненту("ОбщийМакет.RegEx", "Component", ТипВнешнейКомпоненты.Native);
            
Рег = Новый("AddIn.Component.RegEx");
Рег.НайтиСовпадения("Hello world", "([A-Za-z]+)\s+([a-z]+)");

Пока Рег.Следующий() Цикл
    Сообщить(Рег.ТекущееЗначение);    
КонецЦикла; 

Сообщить(Рег.Количество());
Сообщить(Рег.Совпадает("Hello world", "([A-Za-z]+)\s+([a-z]+)"));
Сообщить(Рег.Заменить("Hello world", "([A-Za-z]+)\s+([a-z]+)", "Текст для замены"));

 

44

Скачать файлы

Наименование Файл Версия Размер
RegEx1CAddin_4.zip
.zip 625,61Kb
22.11.18
9
.zip 4 625,61Kb 9 Скачать
RegExMac64_4.so
.so 413,51Kb
22.11.18
1
.so 4 413,51Kb 1 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. Dzenn 273 12.11.18 10:45 Сейчас в теме
Буду гадом ;-) На инфостарте есть что-то про регулярные выражения в 1С на основе механизмов работы с XML. То есть, помещаем в поле-HTML нашу строку, обёрнутую в тэги, запускаем встроенную функцию и получаем ответ. Но не уверен, что это аналог, с регулярками особо не приходилось работать.
4. ImHunter 30 12.11.18 12:39 Сейчас в теме
(1) Есть такое, через XDTO делается. Но такой прием работы предназначен только для валидации строки к паттерну.
Т.е. количество и/или место вхождения паттерна - так не найти.
AlX0id; mivari; 🅵🅾️🆇; A_Max; +4 Ответить
6. A_Max 16 12.11.18 12:47 Сейчас в теме
(1) Там ОООООООЧЕНЬ ограниченный функционал.
2. zykov_vitaliy 7 12.11.18 11:36 Сейчас в теме
Использую
Regexp = Новый COMОбъект("VBScript.RegExp");
3. KAV2 70 12.11.18 11:47 Сейчас в теме
(2) Данная компонента работает также под Linux. В планах собрать под MacOS если будут время и силы.
14. 🅵🅾️🆇 234 12.11.18 17:45 Сейчас в теме
(3) Не думаю, что стоит под огрызок собирать.
Такие компоненты лучше подключать на сервере, вряд ли есть извращенцы хостящиеся на macos (да пусть даже и файловые базы).
5. A_Max 16 12.11.18 12:46 Сейчас в теме
(2) этой штуки нет в linux, а так всё необходимое имеем при себе в базе!
Давно у самого чесались руки самому написать "универсальную" внешнюю компоненту.
7. nixel 539 12.11.18 15:35 Сейчас в теме
Во славу сатане, спасибо огромное!
Labotamy; iliabvf; badboychik; +3 1 Ответить
8. Ershov Mikhail 12.11.18 16:13 Сейчас в теме
Идея хорошая, но поясните один момент:
Текст для анализа, препологается передавать в виде параметра внешней компоненты.
например у меня есть лог файл размером 30 Гб. (Txt), правильно ли я понимаю, что перед тем как передать этот текст внешней компоненте, мне необходимо загрузить его в оперативную память ? ... а в чём тогда смысл этой компоненты ? ведь одно из основных преимуществ регэкспа - это поточная обработка текста, вне зависимости от размера файла, т.е "Часть прочитал, часть отпустил"... а тут получается сначала загрузи всё в оперативную память а потом запускай свой конвеер Regex ... как то "не айс", а текстовым файлом в 100 ГБ я также как и без регекспа имею возможность положить сервер по недостатку памяти. Получается "Кайф" от Regexpa потерян ...
... или я неправ ?
9. KAV2 70 12.11.18 16:19 Сейчас в теме
(8) В данном случае можно использовать объект ЧтениеТекста\TextReader. Этот объект может читать не весь файл целиком , а построчно.
Ershov Mikhail; +1 Ответить
10. Ershov Mikhail 12.11.18 16:22 Сейчас в теме
(9) т.е. сначала я построчно его читаю 1С-ом, а потом передаю Regex компоненте ... но ведь тогда скорость обработки будет примерна такаяже как и без Regexa ... узкое место получается чтение 1С ... а может сделать возможность передавать компоненте путь к файлу ?
11. KAV2 70 12.11.18 16:29 Сейчас в теме
(10)Может быть, но пока не готов по этому поводу ответить.
15. 🅵🅾️🆇 234 12.11.18 17:49 Сейчас в теме
(10) Тут надо работу с потоками придумывать или разбирать ваш файл построчно/поблоково.

Вот 2 варианта для работы с текущей компонентой:
1) воспринимаете ваш файл как ТектовыйДокумент с заданым разделителем и читаете "построчно"
2) с помощью СтрНайти последовательно выгрызаете кусочки с заданым отступом

Ну или вы вовсе не правильно воспринимаете задачу, если это некий xml документ, то вам надо, наверное, смотреть в сторону XPath
17. Ershov Mikhail 12.11.18 17:59 Сейчас в теме
(15) Задача гепотетчиеская, из серии "Разобрать файл тех журнала" ... файл может быть большим, 30-50 ГБ.
Почему именно она ? потому что чаще приходится пользоваться Regex'ом именно для её решения.
В Bash - это делается просто, вопрос в том что если есть компонента, которая смогла бы это делать из 1С, минуя Bash - было бы круто и стало бы платформой для тех или иных решений. Но читать текстовый документ построчно и передавать его в ВК с методами Regexa, в рамках этой задачи - скорее всего сильно проиграет Bash'у по скорости и стабильности работы. Как бы исходя из этих мыслей и попросил пояснить возможно ли на текущий момент, используя эту ВК реализовать нечто подобное.
18. 🅵🅾️🆇 234 12.11.18 18:04 Сейчас в теме
(17) Почему проиграет то?
Не думаю, что кто то будет таким заниматься ради весьма необычной задачи.

Если у вас большой файл и его просто надо переварить компонентой, особо не заморачиваясь - делайте регламентной операцией или длительной задачей.
Если надо срочно и в кратчайшие сроки определенный файл "кушать", то и регэксп и 1с тут не годятся, тк проиграет по скорости специально написанной для этого дела утилите с нормальной асинхронностью и заточенный под поиск определенных паттернов.

ЗЫ: парсеров технологических журналов - вагон и маленькая тележка
19. Ershov Mikhail 12.11.18 18:11 Сейчас в теме
(18) Возможно я не совсем правильно понял заголовка статьи ...
Там написано : "Внешняя компонента для выполнения регулярных выражений".
Мои мысли: "Ух ты, круто т.е. нечто типа "grep DEADLOCK */*.log" можно выполнить из 1с ? ... было бы прикольно...
По факту я должен сначала все файлы через оперативку прогнать а потом пользоваться функционалом Regex'a.
+ Читать файл придётся тоже из 1С ... что (как мне кажется), будет медленнее чем выполнение этой же процедуры в Bash.
Хотя технически, ВК, созданная на сервере 1Сб уже имеет все права сервера 1С, вопрос только в описании функционала...
Это не в коем случае не претензия, это всего лишь мнение.
20. 🅵🅾️🆇 234 12.11.18 18:20 Сейчас в теме
(19) Почему быстрее или медленее то? Зачем вам целиком файл пихать в оперативу, вы всегда так делаете?

Вам надо:
0) подключить обработчик ожидания
1) подключить компоненту
2) в цикле читать файл либо построчно, либо в некий буфер
3) скармливать компоненте
4) после завершения цикла отключить компоненту
Опционально делать это в несколько потоков.
Оперативы потратите метр-другой.

Если мы говорим про написание "просмотр файлов в реальном времени", то это задача скорее для реактивной асинхронщины (нужно выводить данные в поток по мере чтения, не забывая выбрасывать из потока информацию находящуюся далеко от указателя пользователя), синхронно переваривать весь файл целиком чтоб показать пользователю кусочек - плохая идея (именно на этом сыпится большинство редакторов и ide, пытающихся синхронно обработать и разметить весь файл до конца).

Если вам не надо отображать пользователю в реальном времени - то парсите по ночам, как бог пошлет и не парьтесь.
12. azhilichev 148 12.11.18 16:45 Сейчас в теме
(8) Уважаемый, а как вы иначе хотите? Чтобы компонента вам еще и файл читала? Отделяйте мух от котлет.

Автор, если эта компонента работает так, как описал в статье, мысленно жму руку!
13. Ershov Mikhail 12.11.18 16:48 Сейчас в теме
(12) Ну если бы компонента имела возможность читать файл, (А если немного обнаглеть то ещё и маску путей как это работает в Bash) был бы вообще огонь ... но для начала тоже неплохо, ничего против не имею ... это всего лишь идея к развитию проекта ...
Darklight; +1 Ответить
26. Dmitryiv 115 14.11.18 10:22 Сейчас в теме
(8) А может не стоит файлы такого размера обрабатывать средствами 1С? Ну совсем не тот инстумент.
27. Ershov Mikhail 14.11.18 15:49 Сейчас в теме
(26) Создатели конфигурации ЦУП и ЦКК из Корпоративного пакета, считают иначе ... Они пошли дальше, не только парсят их в 1С, ещё и хранят их в РС ... в разобранном виде. На продуктивной БД размером в 1 ТБ, и 200 пользователей в онлайне - Операция "Анализ вызовов кластера" по ТЖ весит 250 Гб , при истории данных в полдня ...
В общем то я их 1Сом и не парсю, для этого используется Bash с Regex'ом. Т.к. это компонента как раз про Regex, думал что может тогда без Bash'a сразу из 1С можно пользоваться Regex'ом ... но видимо не сейчас, возможно когда-нибудь прогресс дойдёт и до полномасштабного Regex'а из 1С.
16. Infactum 268 12.11.18 17:56 Сейчас в теме
А зачем внутри компоненты все эти конвертации типов для linux, если под капотом все работает вокруг шаблонов std::basic_regex и std::basic_string, которые позволяют задать базовый тип (в случае компоненты WCHAR_T)?
22. KAV2 70 13.11.18 05:33 Сейчас в теме
(16) Конвертации лишние и их надо будет убрать. Я оставил это на развитие. Кстати, можно добавлять pull request-ы ;-)
21. kraynev-navi 382 12.11.18 20:27 Сейчас в теме
(0) Вещь! Не делали сравнений по быстродействию с тем же популярным COMОбъект("VBScript.RegExp") ?
23. KAV2 70 13.11.18 05:42 Сейчас в теме
(21) VBscript быстрее, но там есть ещё пути для оптимизации. Не все оптимально сделано. Принципиально что уже сейчас компонента работает на несколько порядков быстрее чем реализация на 1С в конфигурации 1С:Translator.
kraynev-navi; +1 Ответить
24. ayuplotnikov 14.11.18 09:51 Сейчас в теме
Отличная задумка! Успехов вам!
Подскажите, пожалуйста, как управлять флагами i, g, m?
29. KAV2 70 14.11.18 16:41 Сейчас в теме
(24) Честно сказать ни разу не пользовался подобными флагами. Надо будет изучить вопрос.
34. KAV2 70 17.11.18 20:57 Сейчас в теме
(24) В общем, реализация из стандартной библиотеки С++ не поддерживает эти флаги в синтаксисе регулярных выражений. Можно добавить установку этих флагов отдельно, если в них реальная есть потребность, либо за основу взять реализацию не стандартной библиотеки, а скажем boost.
35. ayuplotnikov 18.11.18 09:38 Сейчас в теме
(34) Конкретно для меня критически важен регистронезависимый режим.
Я сейчас в 1С использую VBScript.RegExp. У него эти параметры задаются через булевы свойства Global, IgnoreCase, Multiline. В std::regex - через аргумент конструктора. Существенной разницы между способами я не вижу.
Можно добавить необязательные аргументы к существующим методам или добавить метод, который устанавливает флаги. Все варианты обратно совместимы с текущей реализацией.
25. Darklight 16 14.11.18 10:15 Сейчас в теме
Большое Вам спасибо. Компонента, конечно, замечательная - и я обязательно найду ей применение в своих проектах. А ещё, появление данной публикации, оказалось для меня, как нельзя кстати, я как раз делал свою первую Native компоненты С++ (я совсем не С++ программист) - и уже отчаялся - примеры/шаблоны с ИТС не компилировались, а если заставлял компилироваться - не подключались в 1С. Всё перепробовал. И другие компоненты скачивал - тоже либо не компилировались либо не подключались (на разных платформах и компьютерах и x86 и x64). Думал уже забить на это дело. И тут увидел эту публикацию - и О ЧУДО - она заработала - и на основе шаблона вашей компоненты я сделал свою - и она тоже заработала - АЛИЛУЯ! Но отличия в двух шаблонах так и не нашёл (кроме, разве что не был установлен у меня набор инструментов VS 2017 для XP, использовал набор VS 2013 для XP - но его установка и применение в старом проекте всё-равоно так и не решило проблему), хотя было ещё одно - внешние C++ SDK зависимости (cpp и h) у меня в старом проекте тянулись из каталога SDK версии 7.1, а вашем проекте из SDK версии 8.1 - где и как это настраивается я так и не нашёл (в настройках проекта каталоги в обоих проектах вели именно в SDK версии 7.1). А при применении SDK версии 7.1 с одним из примеров компоненты, скачанной в исходниках из интернета, вообще не компилировался и выдавал ошибку про термы которые "не известны" внутри этого SDK (но мой старый проект, как ни странно, всё-таки компилировался, но компонента не подключалась). В общем, как же это тяжко писать компоненты на VS C++ - спасибо Вам за то, что ваша, вовремя, подоспевшая публикация, помогла мне выбраться из этого тупика! Вот бы ещё разобраться как этот SDK в создаваемых в VS 2017 проектах настроить чтобы знать где же выбирается каталог SDK, откуда должны подтягиваться внешние зависимости (cpp и h).
KAV2; kraynev-navi; +2 Ответить
30. KAV2 70 14.11.18 16:47 Сейчас в теме
(25) Спасибо большое за теплый отзыв! Кстати компонента, собранная на SDK 8 работает и на XP, по крайней мере с SP3 (кажется в одном из сервис паков расширялся формат исполняемых файлов).
28. zakiap 14.11.18 15:58 Сейчас в теме
Похожа на RexV8 только работает медленнее, но зато есть исходники и работа по linux
31. KAV2 70 14.11.18 17:01 Сейчас в теме
(28) Да с производительностью есть куда расти, надеюсь поработать над этим в следующих версиях компоненты.
32. Darklight 16 15.11.18 11:03 Сейчас в теме
(28)
(31) Там в осуждении писали про нестабильную работу RexV8. Проверьте у себя регулярки из поста 62 и ещё нескольких более ранних постов от tormozit.
33. KAV2 70 16.11.18 22:44 Сейчас в теме
(32) Ну на указанных сценариях компонента не падает.
36. KAV2 70 18.11.18 17:40 Сейчас в теме
Добавлена в список загрузок отдельным файлом, внешняя компонента, собранная для Mac OS ( тестировалась и собиралась на версии Sierra 10.12).
К сожалению загрузка компоненты из макета не работает (пока не разобрался в чем дело), поэтому компонента и выложена отдельно, без включения в общий архив, предназначенный для загрузки в макет.
Подключить компоненту можно с помощью метода ПодключитьВнешнююКомпоненту:

ПодключитьВнешнююКомпоненту("<Путь к файлу компоненты>/RegExMac64_4.so", "Component", ТипВнешнейКомпоненты.Native)
Оставьте свое сообщение