Сложный способ организовать проверку строки с помощью регулярного выражения в 1С. При этом ни одна внешняя компонента не пострадала. Ну и от платформы (Linux, MustDie) - не зависит.
(1) neuromancer_aza, у меня Linux, поэтому мне непросто ответить на Ваш вопрос, но Вы всегда можете померять это самостоятельно и рассказать нам. Предположу, что медленнее, если не кешировать объект XDTO, но если кешировать, то может быть и быстрее (если надо один шаблон тестить с многими исходными данными)
{ОбщийМодуль.ДополнительныеПроцедурыКлиент.Модуль(42)}: Ошибка при вызове метода контекста (ПрочитатьXML)
Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);
по причине:
Ошибка разбора XML: - [4,38]
Фатальная ошибка:
xmlParseEntityRef: no name
Не подскажете как быть в данной ситуации? Подозреваю что причина может быть в символе "&"
(2) Sergey Andreev, а что Вы понимаете под "кэшированием объекта"? Как это правильно реализовать, можно примерчик? Мне как раз нужно проверять много строк на соответствие одному шаблону.
Заранее спасибо!
(68) просто добавьте в функцию параметр "test", а в коде функции строки с созданием объекта оберните в блок Если-Тогда-КонецЕсли, в котором проверяйте условие "test = неопределено". Перед первым вызовом напишите "test = Неопределено" (перед циклом проверки). В итоге у Вас функция будет вызываться только первый раз с пустым объектом XDTO, а в следующий раз уже с заполненным, что приведет к использованию уже созданного объекта, а не созданию нового.
Прекрасно!
От себя могу только добавить, что есть еще объекты для работы с XPath, это тоже регулярные выражения, но для уже языков разметки, типа html и xml.
Если добавите и их, будет совсем хорошо!
Роман Цованян.
(4) Поручик, предположу, что если сохранять объект XDTO, то и в цикле будет быстро. Если же каждый раз фабрикой создавать пакет, то. полагаю, при множественном использовании производительность будет не очень.
(3) pfihr, здесь используется встроенная в 1С проверка типа по фасету для значения поля XDTO-объекта, так что, полагаю, добавить сюда ХPath совсем не получится )))
(7) Xershi, ниже я привел часть синтаксиса с примерами. В коде есть пример для проверки даты: ПроверитьСтроку("01.01.2012","\d{2}\.\d{2}\.\d{4}") - сравните с описанием регулярных выражений ниже по тексту и попробуйте разобрать данный пример. Я сам с регулярками раза с третьего только разобрался, а первые два подхода вызвали лишь мысли о том, что пока мне это не сильно надо, но выглядит как-то сложно и времени потратить надо будет немало, а его, типа, у меня нет. Но когда действительно появилась необходимость в их освоении, то оказалось, что достаточно дня, чтобы разобраться.
(9) Xershi, быстрее освоить материал - это взять и написать регулярки для тестирования каких-то реальных вещей. Например, даты, e-mail, адреса сайта, имени переменной, числа, почтового адреса с индексом, ... - вот реализуйте каждый из них - и Вы сразу же станете специалистом. Описанной в статье информации для этого уже должно хватить. А если что-то непонятно - всегда есть гугл, он куда терпеливей иных учителей и никогда не отказывает пытливому уму в предоставлении ссылок на искомое.
Кстати, господа, в notepad++ есть поиск и замена на основе регулярных выражений. Я так иногда на работе что-то искал и менял, чтобы потом в консоль запросов вставить, как список. Вот там как раз непочатый край для экспериментов с регулярными выражениями. Например, попробуйте все даты в тексте заменить на какую-то конкретную дату - уже расширите горизонты своего познания и огребете достаточно экспы для очередного левелапа )))
(18) karapuzzzz, а Вы кешировали объект XDTO или выполняли процедуру целиком? У Вас в коде правильным адресом будет и "%;№!@:?*!.", ибо вы не проверяете на "букву, цифру и подчеркивание" - реальный адрес куда сложнее. при том валидный "iem.mycompany@holding.com" не пройдет проверку по регулярке, ибо валидная "." приведет к ошибке. Т.е. не все так просто в действительности )))
(23) Yashazz, ну как бы тут было два момента: выгрузка отчета по схеме XSD, любезно предосиавленная ПФР, которая отказалась грузиться в пакет и вынудила исследовать механизм XDTO. Потом была статья на ИС, в которой кто-то реализовал алгоритм регулярок. Я было подумал, а не выгрузить ли мне пакет в модель с прикрученным типом и менять паттерн проверки у этого типа... И, в итоге, сработало как видите...
ЗЫ: про XDTO еще месяц назад ничего толком не знал, а теперь знаю о нем весьма много.
Если не секрет, что изучали для познания дзен XDTO?
"Чтобы в чем-то разобраться нужна задача и сержант с сапогом, периодически пинающим под зад" (Я)
Исходя из вышесказанного могу порекомендовать статьи "ХДТО - это просто" на Инфостарте (серия из трех статей, если не ошибаюсь - оттуда, в частности, почерпнута идея о сериализации модели). Ну и сержанта Вам с сапогом ))))
Кстати, у меня друг один все заставлял меня с регулярками разобраться - я болт забивал после прочтения пары строк из Вики. Но когда внезапно появилась задача, то я не только за день с ними вполне себе разобрался, но и написал механизм преобразования 1С-ной маски поля в регулярное выражение. правда тогда проверка была реализована на мелкософтовское регэкспе, но бывали случаи, когда СОМ тупо отваливался (баги нескольких платформ) и при инициализации любого СОМ-объекта система валилась с ошибкой. Исходя из этого мысль о реализации теста регулярок средствами платформы постоянно висела в голове. И как только я узнал, что в типах ХДТО есть возможность использовать паттерны проверки, то это сразу же материализовалось в вышеприведенный код.
Решалось рестартом сервера приложений. Также проблема появляется при одновременной инициализации на сервере СОМ-объекта несколькими сеансами/потоками. Решение описал тут.
Но когда внезапно появилась задача, то я не только за день с ними вполне себе разобрался, но и написал механизм преобразования 1С-ной маски поля в регулярное выражение.
Я даже помню, в какой организации это было :-)
Тоже потребовалось добавить проверку с помощью регулярок, но на Linyx регэксп уже не помог. Спасибо за рабочий пример и большой привет со старой работы!
Проверка паттерна конечно полезна. Но например в ИР соотношение проверки паттерна и поиска по паттерну составляет 1:100. Поэтому название публикации не совсем корректное. Корректнее было бы "Проверка регулярного выражения без внешних компонент? Легко!"
(27) Fragster, 1с использует в своем коде библиотеку icu - в ней все это, на сколько я знаю, есть. Что мешает им реализовать все это в языке - для меня загадка. Поэтому без внешних компонент только проверка.
чота рано порадовался ) как только решил применить реально, получил:
{Форма.Форма.Форма(102)}: Ошибка при вызове конструктора (ФабрикаXDTO)
МояФабрикаXDTO = Новый ФабрикаXDTO(Модель);
по причине:
Ошибка проверки данных XDTO:
Значение: '\d*\.\d*\.\d*\.\d*\:\d*' не соответствует простому типу: {sample-my-package}testtypes
Несоответствие фасету Pattern = '\d*\.\d*\.\d*\.\d*\:\d*'
по причине:
failed to compile: xmlFAParseRegExp: extra characters
При вот такой проверке:
Сообщить(ПроверитьСтроку("1.233.54.55:80","\d*\.\d*\.\d*\.\d*\:\d*"));
(32) AlX0id, а перед ":" зачем слеш обратный? Уберите его - и все заработает. Обратный слеш только перед спецсимволами можно ставить. В иных случаях регулярное выражение не будет валидным и система будет падать уже на попытке преобразования модели в XDTO-пакет. Можете а этом месте в код добавить проверку на криворуких программистов, чтобы система возвращала им вместо истины или лжи строку "криворукий программер написал неверное регулярное выражение" )))
Доработал аналогичную идею, на днях выкачу поиск по шаблону.
Для улучшения производительности сделал предварительную компиляцию выражения (создание XDTO-объекта и сохранение в структуру)
Есть крайне простой тест производительности.
Коллеги, возник следующий вопрос: пишу в образце простое выражение "тест" и строку поиска "тестовый текст". Совпадений не находит. Если использовать то же самое, но при помощи VBScript.RegExp, то результат положительный. В XDTO какой-то "свой" синтаксис регулярных выражений?
(40) в данном случае отрабатывает именно паттерн, т.е. проверяется соответствие образцу, а не выполняется поиск подстроки в образце. Смысл данного механизма - ограничивать данные в поле. Если Вы в качестве паттерна пишите "тест", то "тестовый текст" у Вас не будет равен "тест", но если задача стоит проверить на наличие во входящем потоке слова "тест", то нужно использовать ".*тест.*" (т.е. указать в шаблоне, что до и после слова "тест" могут следовать (или не следовать) любые символы.
(41), да я именно так и хотел. Я тоже вписывал в паттерн ".*тест.*" и "тестовый текст" удовлетворял поиску по шаблону. Я думал, что 1С использует в качестве шаблона стандартный синтаксис регулярных выражений, поэтому писал шаблон как и в VBScript.RegExp. Получается, что синтаксис отличается? Если да, то где можно посмотреть синтаксис, который используется при проверке в платформе? К примеру: хочу проверить, что во входящем потоке есть слова, начинающиеся с "test". В VBScript.RegExp написал бы паттерн "\btest". 1С такой паттерн принимать отказывается.
P.S.: кстати, если в VBScript.RegExp попытаться вписать в паттерн "\bтест", то вхождения в потоке "тестовый текст" тоже не найдутся. В инете нашел, что это связано с локализацией. В PHP можно просто указать флаг /u, тогда начинает адекватно работать с кириллицей.
(42) синтаксис не отличается, но нужно иметь ввиду, что в данном случае 1С проверяет соответствие шаблону, а не осуществляет поиск подстроки. Тут необходимо уловить разницу между наличием в строке подстроки, соответствующей шаблону, и когда строка вся целиком соответствует шаблону. Т.е. при таком подходе нельзя делать так, как делали Вы - нужно добавлять ".*" с обоих сторон (как % при ПОДОБНО в запросе).
Самое нормальное решение данной проблемы встроенными средствами 1С которое я видел ! Вопрос о включении функционала регулярных выражений в язык 1С поднималось на форуме разработчиков не единожды, но разрабы считают, что всегда есть вопросы поважнее и все прекрасно работает без регулярок.
(56) ответил в почте, повторюсь здесь: для 1С в паттерне проверяется шаблон, поэтому нужды в описателях начала и конца строки нет никаких, более того - 1С на них ругается. Поэтому можно смело грохать ^ и $, ибо ^\d+$ в случае XDTO-паттерна будет равнозначна просто \d+.
Коллега интереса ради проверил работоспособность механизма проверки регулярок с помощью описанной в статье функции и пришел к следующим выводам:
1. regExp работает в три раза быстрее (COM-объект) при условии, что COM-объект регэкспа кешируется. В принципе я не удивлен - 1С скорее всего для icu сделала нехилый и тромозящий враппер, чтобы все это работало.
2. В XDTO не поддерживаются ссылки (типа \1 \2 ...). Т.е. проверить, что у вас первое слово не повторяется - нереально.
Печалька, конечно, но сам механизм рабочий и позволяет что-то такое провернуть не только под виндой. Думаю, что создам внешнюю нативную компоненту для Linux, чтобы работало не медленнее RegExp'а.
Смотря чего и где искать. Для "массива совпадений" в небольшом XML может подойти XPath, реализованный в 1С для объекта DOM. Если что-то более серьезное, то иногда проще захардкодить что-то типа "А = СтрРазделить(Строка, "|")". Но если очень охота все отдать на откуп настройщикам универсального механизма, то без RegExp никак (в Linux можно через "sed -e" или "grep" получить все, что душе угодно).
(72)
многострочный текст придется по одной строке проверять. как вариант Для Индекс=1 по СтрЧислоСтрок(Текст) Цикл
// СтрПолучитьСтроку(Текст,Индекс) - Получает строку многострочной строки по номеру.
Вставляем Маркер начала строки, например, знак @ и парсим начиная шаблон с него.
СтрТекста="@"+СтрПолучитьСтроку(Текст,Индекс);
И наконец,
Сообщить(ПроверитьСтроку("СтрТекста","@.*"));
(0) А подскажите, как проверить с учетом кирилицы?
Например есть строка: Купить мороженное завтра в 15:00 Регулярное выражение: (завтра в )\d{2}:\d{2}
По идее все правильно (обычно все тестирую https://regex101.com/), но вот из 1С вашим способом не работает. Как воспользоваться?
Спасибо! Классная идея.
PS: Вообще не совсем понятно, почему до сих пор в платформе нет нормальных регулярных выражений встроенных в платформу.
(83) в сообщении (70) есть ответ, только я все равно не понимаю.
Функция ПроверитьСтроку(Строка, Фасет, ПервыйВызов=Истина)
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(
"<Model xmlns=""http://v8.1c.ru/8.1/xdto"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:type=""Model"">
|<package targetNamespace=""sample-my-package"">
|<valueType name=""testtypes"" base=""xs:string"">
|<pattern>" + Фасет + "</pattern>
|</valueType>
|<ob jectType name=""TestObj"">
|<property xmlns:d4p1=""sample-my-package"" name=""TestItem"" type=""d4p1:testtypes""/>
|</objectType>
|</package>
|</Model>");
Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);
// Для "кеширования" - ускоряет вызов в цикле
Если ПервыйВызов=Истина Тогда
МояФабрикаXDTO = Новый ФабрикаXDTO(Модель);
КонецЕсли;
Пакет = МояФабрикаXDTO.Пакеты.Получить("sample-my-package");
Тест = МояФабрикаXDTO.Создать(Пакет.Получить("TestObj"));
Попытка
Тест.TestItem = Строка;
Возврат Истина
Исключение
Возврат Ложь
КонецПопытки;
КонецФункции
Показать
допустим, первый раз вызвали в цикле, фабрика создалась.
потом вне функции перед вторым ее вызовом мы меняем переменную на Ложь, чтобы объект не создавался.
но не пойму где его хранить с первого вызова?
извиняюсь за тупость
(84) Если разные строки на РАЗНЫЕ фасеты, то придется создать фабрику каждый раз, т.к. я, лично, не знаю способа переопределения типа в уже созданной фабрике.
А если фасет одинаковый, то его можно и закешировать. Хранить кеш нужно в вызывающей функции.
Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);
по причине:
Ошибка разбора XML: - [6,14]
Фатальная ошибка:
Specification mandate value for attribute jectType
Не указали что есть вариант использования условий:
Вертикальная черта разделяет допустимые варианты. Например, gray|grey соответствует gray или grey
т.е. для проверки дат "01.01.20" и 01.01.2019 может выполняться одним фасетом = "\d{2}\.\d{2}\.(\d{4}|\d{2})"
(89) книжкой, описывающей почти все нюансы работы с регулярными выражениями, можно убить. Что Вы хотите от статьи? Почему не жалуетесь, что про группы не написано?
https://youtu.be/5UAVMSiMnnk Т.е. вопрос примерно такой - могут ли вообще к 1с каким то образом прикручиваться чудесные линуксовые файловые утилиты (любые)?
могут ли вообще к 1с каким то образом прикручиваться чудесные линуксовые файловые утилиты (любые)?
А в чем проблема? Любая файловая утилита может взять данные из файла и положить результат в файл. Для того, чтобы использовать это в 1С, можно просто писать в файл что-то, что нужно обработать, вызвать чудесную команду системы (тот же grep -e, например) и попросить записывать результат в файл. Потом файл читаем и данные в нем рассовываем по массивам/соответствиям/структурам - что нам больше нравится. И тут можно и подстроки искать, и вхождения, и просто проверять по регулярке - любой каприз. Но, опять же, в винде это работать не будет, ибо нет в ней "искаропки" grep'а, sed'а и прочих "чудесных утилит".
С точки зрения ОСи, то что либу подключить как СОМ-объет, что команду системы выполнить - все-равно файл прочитать и выполнить. Другое дело, что СОМ можно создать однажды и вызвать много раз, а команда системы будет каждый раз вызываться "заново". С другой стороны, ОСь все-равно закеширует исполняемый файл и читать его каждый раз с диска не будет, а вот пачку системных вызовов все-равно исполнит.
(94) а чем отличается подключение grep e с точки зрения 1с от любимого всеми апача ? Или это тоже 1с- файл -утилита-файл-1с?
Или у 1с есть метод для подключения апача, но нет метода для grep?