Регулярные выражения без внешних компонент? Легко!

Сложный способ организовать проверку строки с помощью регулярного выражения в 1С. При этом ни одна внешняя компонента не пострадала. Ну и от платформы (Linux, MustDie) — не зависит.

Здравствуйте, товарищи! 

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

Код:

&НаКлиенте
Функция ПроверитьСтроку(Строка, Фасет)
Чтение = Новый Чтение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>
|<objectType 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 = Строка;
Возврат Истина
Исключение
Возврат Ложь
КонецПопытки;

КонецФункции

&НаКлиенте
Процедура Модель(Команда)

Сообщить(ПроверитьСтроку("01.01.2012","d{2}.d{2}.d{4}"));
Сообщить(ПроверитьСтроку("01.01.20121","d{2}.d{2}.d{4}"));

КонецПроцедуры

Все.

Для тех, кому мало…

Итак, лет этак эндцать назад программисты решили упростить поиск, замену и проверку на соответвие различных строк, т.к. им, полагаю, надоело каждый раз писать что-то типа:

Если Сред(стрДата,1,1) < "0" ИЛИ Сред(стрДата,1,1) > "9" Тогда Ошибка = Истина;
КонецЕсли;

Если Сред(стрДата,2,1) < "0" ИЛИ Сред(стрДата,2,1) > "9" Тогда Ошибка = Истина;
КонецЕсли;

Если Сред(стрДата,3,1) <> "." Тогда Ошибка = Истина;
КонецЕсли;

//...

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

Ошибка = НЕ ПроверитьСтроку(СтрДата, "d{2}.d{2}.d{4}");

Да, грамотным разработчикам стало ой как просто. Но что делать остальным? Правилный ответ, конечно, — учиться, учиться и еще раз  учиться! )))

 

Итак, самое простое, что нужно, чтобы освоить шаблоны проверки:

. — любой символ

+ — один или более раз, пример «.+» — один или более любой символ.

* — ноль или более раз, пример «.*» — любое количество любых символов (даже ни одного).

[n-m] — символ от m до n, пример: «[0-9]+» — одна или более цифр(а).

d — цифра, пример d+ — одна или более цифр(а).

D — не цифра.

s — пробельный символ — ТАБ, пробел, перенос строки, возврат каретки и т.п.

S — непробельный символ.

w — буква, цифра, подчеркивание.

W — не буква, не цифра и не подчеркивание соответственно.

#k8SjZc9Dxk — начало текста, например «#k8SjZc9Dxkd+» — строка начинается с цифры.

$ — конец текста, например «D+$» — строка заканчивается НЕ цифрой.

{m,n} — шаблон для от m до n символов, например «d{2,4}» — от двух до четырех цифр. Можно указать одну и всего цифру для строгого соответвия.

— экранирует спецсимволы. Например, «.» — символ точки.

89 Comments

  1. neuromancer_aza

    Здравствуйте. Замеряли скорость работы? Как оно в скорости, например, с тем же VBScript.RegExp?

    Reply
  2. starik-2005

    (1) neuromancer_aza, у меня Linux, поэтому мне непросто ответить на Ваш вопрос, но Вы всегда можете померять это самостоятельно и рассказать нам. Предположу, что медленнее, если не кешировать объект XDTO, но если кешировать, то может быть и быстрее (если надо один шаблон тестить с многими исходными данными)

    Reply
  3. pfihr

    Прекрасно!

    От себя могу только добавить, что есть еще объекты для работы с XPath, это тоже регулярные выражения, но для уже языков разметки, типа html и xml.

    Если добавите и их, будет совсем хорошо!

    Роман Цованян.

    Reply
  4. Поручик

    Оригинально. Интересно, как оно будет работать в цикле.

    Reply
  5. starik-2005

    (4) Поручик, предположу, что если сохранять объект XDTO, то и в цикле будет быстро. Если же каждый раз фабрикой создавать пакет, то. полагаю, при множественном использовании производительность будет не очень.

    (3) pfihr, здесь используется встроенная в 1С проверка типа по фасету для значения поля XDTO-объекта, так что, полагаю, добавить сюда ХPath совсем не получится )))

    Reply
  6. AlX0id

    Круто %)

    А какой язык регулярок используется в фасетах?

    Reply
  7. Xershi

    Было бы не плохо добавить блок, который бы описывал как на практике это использовать.

    А то после прочтения не стало понятнее как это употреблять.

    Reply
  8. starik-2005

    (6) AlX0id, ИМХО тот же, что и в RegExp от M$.

    (7) Xershi, ниже я привел часть синтаксиса с примерами. В коде есть пример для проверки даты: ПроверитьСтроку(«01.01.2012″,»d{2}.d{2}.d{4}») — сравните с описанием регулярных выражений ниже по тексту и попробуйте разобрать данный пример. Я сам с регулярками раза с третьего только разобрался, а первые два подхода вызвали лишь мысли о том, что пока мне это не сильно надо, но выглядит как-то сложно и времени потратить надо будет немало, а его, типа, у меня нет. Но когда действительно появилась необходимость в их освоении, то оказалось, что достаточно дня, чтобы разобраться.

    Reply
  9. Xershi

    (8) поэтому и говорю. Было бы не плохо чтобы эту тему разжевали более подробно. Так было бы быстрее освоить материал!

    Reply
  10. starik-2005

    (9) Xershi, быстрее освоить материал — это взять и написать регулярки для тестирования каких-то реальных вещей. Например, даты, e-mail, адреса сайта, имени переменной, числа, почтового адреса с индексом, … — вот реализуйте каждый из них — и Вы сразу же станете специалистом. Описанной в статье информации для этого уже должно хватить. А если что-то непонятно — всегда есть гугл, он куда терпеливей иных учителей и никогда не отказывает пытливому уму в предоставлении ссылок на искомое.

    Reply
  11. retif

    интересно,надо будет проверить скорость работы

    Reply
  12. webester

    (7)Пробегите хотя бы бегло Дж.Фридл — Регулярные выражения. Уйдут все вопросы.

    Reply
  13. starik-2005

    Кстати, господа, в notepad++ есть поиск и замена на основе регулярных выражений. Я так иногда на работе что-то искал и менял, чтобы потом в консоль запросов вставить, как список. Вот там как раз непочатый край для экспериментов с регулярными выражениями. Например, попробуйте все даты в тексте заменить на какую-то конкретную дату — уже расширите горизонты своего познания и огребете достаточно экспы для очередного левелапа )))

    Reply
  14. Xershi

    (12) webester, если будет задача, я просто погуглю, а пока просто хотел, чтобы улучшили статью, чтобы начинающим не пришлось гуглить)

    Reply
  15. AlX0id

    (13)

    Ну уж тогда Regex Buddy можно поставить, для полноты ощущений 🙂

    Reply
  16. maxx

    Здорово.

    А не подскажете почему в конфигураторе при определении XTDO пакета визуально свойства pattern не видно?

    Reply
  17. starik-2005

    (16) maxx, это свойство есть только у типа данных.

    Reply
  18. karapuzzzz

    Регулярки это найс. Спасибо огромное автору за хорошую альтернативу внешним компонентам.

    А теперь тестирование. За основу взял проверку адреса электронной почты:

    Регулярка: «w+@w+.w+»

    Текст проверки 1С:

    ПозицияСобаки = Найти(СтрокаАнализа, «@»);
    СтрокаПослеСобаки = Сред(СтрокаАнализа, ПозицияСобаки);
    ПозицияТочки =  Найти(СтрокаПослеСобаки, «.»);
    
    Если ПозицияСобаки > 1
    И ПозицияТочки > 1 Тогда
    
    //
    
    КонецЕсли;

    Показать

    На 100000 итераций код 1С отработал за 2сек, а регулярные выражения 63с

    Reply
  19. starik-2005

    (18) karapuzzzz, а Вы кешировали объект XDTO или выполняли процедуру целиком? У Вас в коде правильным адресом будет и «%;№!@:?*!.», ибо вы не проверяете на «букву, цифру и подчеркивание» — реальный адрес куда сложнее. при том валидный «iem.mycompany@holding.com» не пройдет проверку по регулярке, ибо валидная «.» приведет к ошибке. Т.е. не все так просто в действительности )))

    Reply
  20. starik-2005

    (18) karapuzzzz, попробовал с кешем объекта XDTO и паттерном «[0-z]+@[0-z]+.[0-z]+»:

    Время начала: 63 593 123 364 131

    Длительность: 999 мс

    Истинных: 100 000

    Время начала: 63 593 123 365 130

    Длительность: 280 мс

    Код какой-то такой получился:

     ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
    Сообщить(«Время начала: » + ВремяНачала);
    Для А = 1 ПО 100000 Цикл
    Результат = ПроверитьСтроку(ОбъектХ, СтрокаАнализа, «[0-z]+@[0-z]+.[0-z]+»);
    Если Результат Тогда Сч = Сч + 1;
    КонецЕсли;
    КонецЦикла;
    Сообщить(«Длительность: » + (ТекущаяУниверсальнаяДатаВМиллисекундах() — ВремяНачала));
    Сообщить(«Истинных: » + Сч);
    
    
    ВремяНачала = ТекущаяУниверсальнаяДатаВМиллисекундах();
    Сообщить(«Время начала: » + ВремяНачала);
    Для А = 1 ПО 100000 Цикл
    
    Результат = Ложь;
    ПозицияСобаки = Найти(СтрокаАнализа, «@»);
    СтрокаПослеСобаки = Сред(СтрокаАнализа, ПозицияСобаки);
    ПозицияТочки =  Найти(СтрокаПослеСобаки, «.»);
    
    Если ПозицияСобаки > 1
    И ПозицияТочки > 1 Тогда
    
    Результат = Истина;
    
    КонецЕсли;
    
    КонецЦикла;
    Сообщить(«Длительность: » + (ТекущаяУниверсальнаяДатаВМиллисекундах() — ВремяНачала));
    
    

    Показать

    Reply
  21. maxx

    (17) в определении типа тоже не увидел свойства pattern, хотя есть другие свойства фасета (максим. , миним. длины)

    Reply
  22. starik-2005

    (21) maxx, ну, это, …

    Reply
  23. Yashazz

    Класс! Просто фантастика. Круть неимоверная, зачёт однозначный.

    Совершенно шикарная идея, и ведь правда работает. Неистово плюсую.

    Если не секрет, как до такого додумались? Что натолкнуло?

    Reply
  24. starik-2005

    (23) Yashazz, ну как бы тут было два момента: выгрузка отчета по схеме XSD, любезно предосиавленная ПФР, которая отказалась грузиться в пакет и вынудила исследовать механизм XDTO. Потом была статья на ИС, в которой кто-то реализовал алгоритм регулярок. Я было подумал, а не выгрузить ли мне пакет в модель с прикрученным типом и менять паттерн проверки у этого типа… И, в итоге, сработало как видите…

    ЗЫ: про XDTO еще месяц назад ничего толком не знал, а теперь знаю о нем весьма много.

    Reply
  25. fvadim

    я правильно понимаю, что этот метод годится только для проверки на соответствие шаблону и получение сабматчей реализовать не получится?

    Reply
  26. tormozit

    Проверка паттерна конечно полезна. Но например в ИР соотношение проверки паттерна и поиска по паттерну составляет 1:100. Поэтому название публикации не совсем корректное. Корректнее было бы «Проверка регулярного выражения без внешних компонент? Легко!»

    Reply
  27. Fragster

    Проверка — замечательно. Но часто нужна замена и/или данные по началу и длине найденных фрагментов (опять же, их может быть более одного)

    Reply
  28. starik-2005

    (27) Fragster, 1с использует в своем коде библиотеку icu — в ней все это, на сколько я знаю, есть. Что мешает им реализовать все это в языке — для меня загадка. Поэтому без внешних компонент только проверка.

    Reply
  29. starik-2005

    Кстати, рекомендую: http://icu-project.org/apiref/icu4c/uregex_8h.html

    Reply
  30. AndreykO

    Спасибо. Очень помогло. Всё работает.

    Reply
  31. starik-2005

    (30) AndreykO, всегда пожалуйста.

    Reply
  32. AlX0id

    чота рано порадовался ) как только решил применить реально, получил:

    {Форма.Форма.Форма(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*»));

    Reply
  33. starik-2005

    (32) AlX0id, а перед «:» зачем слеш обратный? Уберите его — и все заработает. Обратный слеш только перед спецсимволами можно ставить. В иных случаях регулярное выражение не будет валидным и система будет падать уже на попытке преобразования модели в XDTO-пакет. Можете а этом месте в код добавить проверку на криворуких программистов, чтобы система возвращала им вместо истины или лжи строку «криворукий программер написал неверное регулярное выражение» )))

    Reply
  34. orefkov

    (15) AlX0id, (15) AlX0id, зачем Regex Buddy, когда есть это:

    Reply
  35. herfis

    Прикольно! Жалко, что только проверка…

    Для теста регулярок я разное пробовал, но руки зацепились почему-то именно за regexr.com

    Reply
  36. b00t

    regex1c (github)

    Доработал аналогичную идею, на днях выкачу поиск по шаблону.

    Для улучшения производительности сделал предварительную компиляцию выражения (создание XDTO-объекта и сохранение в структуру)

    Есть крайне простой тест производительности.

    Reply
  37. binex
    s — пробельный символ — ТАБ, пробел, перенос строки, возврат каретки и т.п.

    Это только пробельный символ.

    Перевод строки, табуляция —
    и , соответственно.

    Reply
  38. starik-2005

    (37)

    Это только пробельный символ.

    Идем учить мат.часть:

    Reply
  39. alexkon

    (34), а где такой редактор взять?

    Reply
  40. alexkon

    Коллеги, возник следующий вопрос: пишу в образце простое выражение «тест» и строку поиска «тестовый текст». Совпадений не находит. Если использовать то же самое, но при помощи VBScript.RegExp, то результат положительный. В XDTO какой-то «свой» синтаксис регулярных выражений?

    Reply
  41. starik-2005

    (40) в данном случае отрабатывает именно паттерн, т.е. проверяется соответствие образцу, а не выполняется поиск подстроки в образце. Смысл данного механизма — ограничивать данные в поле. Если Вы в качестве паттерна пишите «тест», то «тестовый текст» у Вас не будет равен «тест», но если задача стоит проверить на наличие во входящем потоке слова «тест», то нужно использовать «.*тест.*» (т.е. указать в шаблоне, что до и после слова «тест» могут следовать (или не следовать) любые символы.

    Reply
  42. alexkon

    (41), да я именно так и хотел. Я тоже вписывал в паттерн «.*тест.*» и «тестовый текст» удовлетворял поиску по шаблону. Я думал, что 1С использует в качестве шаблона стандартный синтаксис регулярных выражений, поэтому писал шаблон как и в VBScript.RegExp. Получается, что синтаксис отличается? Если да, то где можно посмотреть синтаксис, который используется при проверке в платформе? К примеру: хочу проверить, что во входящем потоке есть слова, начинающиеся с «test». В VBScript.RegExp написал бы паттерн «test». 1С такой паттерн принимать отказывается.

    P.S.: кстати, если в VBScript.RegExp попытаться вписать в паттерн «тест», то вхождения в потоке «тестовый текст» тоже не найдутся. В инете нашел, что это связано с локализацией. В PHP можно просто указать флаг /u, тогда начинает адекватно работать с кириллицей.

    Reply
  43. starik-2005

    (42) синтаксис не отличается, но нужно иметь ввиду, что в данном случае 1С проверяет соответствие шаблону, а не осуществляет поиск подстроки. Тут необходимо уловить разницу между наличием в строке подстроки, соответствующей шаблону, и когда строка вся целиком соответствует шаблону. Т.е. при таком подходе нельзя делать так, как делали Вы — нужно добавлять «.*» с обоих сторон (как % при ПОДОБНО в запросе).

    Reply
  44. sergzhel

    Доступен ли многострочный режим и получение количество вхождений, игнорирование регистра?

    Reply
  45. starik-2005

    (44) только тест.

    Reply
  46. clition

    Не помню чьё: «Если у вас есть проблема, и вы собираетесь её решать с помощью регулярных выражений, тогда у вас будет уже две проблемы.»

    Reply
  47. starik-2005

    (46)

    Не помню чьё

    «Ученье — свет, а неученье — чуть свет и на работу…» (с) Народ.

    Reply
  48. frkbvfnjh

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

    Reply
  49. frkbvfnjh

    (24)

    ЗЫ: про XDTO еще месяц назад ничего толком не знал, а теперь знаю о нем весьма много.

    Если не секрет, что изучали для познания дзен XDTO? Сам толком не вкурил эту тему, но очень хочется досконально в этом разбираться…

    Reply
  50. starik-2005

    (49)

    Если не секрет, что изучали для познания дзен XDTO?

    «Чтобы в чем-то разобраться нужна задача и сержант с сапогом, периодически пинающим под зад» (Я)

    Исходя из вышесказанного могу порекомендовать статьи «ХДТО — это просто» на Инфостарте (серия из трех статей, если не ошибаюсь — оттуда, в частности, почерпнута идея о сериализации модели). Ну и сержанта Вам с сапогом ))))

    Кстати, у меня друг один все заставлял меня с регулярками разобраться — я болт забивал после прочтения пары строк из Вики. Но когда внезапно появилась задача, то я не только за день с ними вполне себе разобрался, но и написал механизм преобразования 1С-ной маски поля в регулярное выражение. правда тогда проверка была реализована на мелкософтовское регэкспе, но бывали случаи, когда СОМ тупо отваливался (баги нескольких платформ) и при инициализации любого СОМ-объекта система валилась с ошибкой. Исходя из этого мысль о реализации теста регулярок средствами платформы постоянно висела в голове. И как только я узнал, что в типах ХДТО есть возможность использовать паттерны проверки, то это сразу же материализовалось в вышеприведенный код.

    Reply
  51. frkbvfnjh

    (50)

    при инициализации любого СОМ-объекта система валилась с ошибкой.

    У меня та же фигня… Спасибо за наводку!

    Reply
  52. starik-2005

    (51)

    У меня та же фигня… Спасибо за наводку!

    Решалось рестартом сервера приложений. Также проблема появляется при одновременной инициализации на сервере СОМ-объекта несколькими сеансами/потоками. Решение описал тут.

    Reply
  53. frkbvfnjh

    Афигеть, спасибо, узнаю сегодня много нового…

    Reply
  54. PavleG29

    (50)

    Но когда внезапно появилась задача, то я не только за день с ними вполне себе разобрался, но и написал механизм преобразования 1С-ной маски поля в регулярное выражение.

    Я даже помню, в какой организации это было 🙂

    Тоже потребовалось добавить проверку с помощью регулярок, но на Linyx регэксп уже не помог. Спасибо за рабочий пример и большой привет со старой работы!

    Reply
  55. starik-2005

    (54)

    Я даже помню, в какой организации это было 🙂

    Ну тогда ты должен знать, почему я тогда в ХДТО ничего не понимал! ))) (потому что сержант пинал Диму, а не меня)

    ЗЫ: Тоже всем привет!

    Reply
  56. wbazil

    Тестирую, получаю «удивительный» результат, может кто сказать почему?

    Сообщить(ПроверитьСтроку(«778987», «#k8SjZc9Dxkd+$»));     //возвращает Ложь
    
    RegExp = Новый COMОбъект(«VBScript.RegExp»);
    RegExp.Pattern =  «#k8SjZc9Dxkd+$»;
    Сообщить(RegExp.Test(«778987»));   //возвращает Истину
    
    ПроверитьСтроку функция из (0)
    Reply
  57. starik-2005

    (56) ответил в почте, повторюсь здесь: для 1С в паттерне проверяется шаблон, поэтому нужды в описателях начала и конца строки нет никаких, более того — 1С на них ругается. Поэтому можно смело грохать #k8SjZc9Dxk и $, ибо #k8SjZc9Dxkd+$ в случае XDTO-паттерна будет равнозначна просто d+.

    Reply
  58. Diversus

    Скажите, а предложенный вариант будет работать на серверной 1С, которая установлена на Linux?

    Reply
  59. starik-2005

    (58) будет.

    Reply
  60. FilatovRA

    ПроверитьСтроку(СокрЛП(НомерГТД), «d{8}/d{6}/d{7}/d+»); Соответственно для проверки номеров ГТД, наверняка пригодится.

    Reply
  61. starik-2005

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

    1. regExp работает в три раза быстрее (COM-объект) при условии, что COM-объект регэкспа кешируется. В принципе я не удивлен — 1С скорее всего для icu сделала нехилый и тромозящий враппер, чтобы все это работало.

    2. В XDTO не поддерживаются ссылки (типа 1 2 …). Т.е. проверить, что у вас первое слово не повторяется — нереально.

    Печалька, конечно, но сам механизм рабочий и позволяет что-то такое провернуть не только под виндой. Думаю, что создам внешнюю нативную компоненту для Linux, чтобы работало не медленнее RegExp’а.

    Reply
  62. It-developer

    Блин, фигово, что нет в платформе. Одни велосипеды

    Reply
  63. andrey314

    (2)

    При использовании данным способом шаблона:

    ШаблонПоиска = «#k8SjZc9Dxk!{0,1}([0-9A-Za-z*]{9,})&([0-9|.]{1,})$»;

    такая ошибка:

    {ОбщийМодуль.ДополнительныеПроцедурыКлиент.Модуль(42)}: Ошибка при вызове метода контекста (ПрочитатьXML)

    Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);

    по причине:

    Ошибка разбора XML: — [4,38]

    Фатальная ошибка:

    xmlParseEntityRef: no name

    Не подскажете как быть в данной ситуации? Подозреваю что причина может быть в символе «&»

    Reply
  64. starik-2005

    (63) 1C, на сколько я помню, не умеет «$» и «#k8SjZc9Dxk», т.к. для проверки шаблона эти символы не нужны. Попробуйте убрать их из строки.

    По поводу «&» — то это символ? На сколько я знаю (и вики — тоже) — амперсанд — это обычный символ, на него ничто ругаться не должно…

    ЗЫ: также, возможно Вы зря заэкранировали «!». Т.е. не нужно писать «!» — нужно просто «!».

    ШаблонПоиска = «!{0,1}([0-9A-Za-z*]{9,})&([0-9|.]{1,})»;
    Reply
  65. andrey314

    (64)

    Да спасибо.

    Действительно, убрал «$» и «#k8SjZc9Dxk» а вместо «&» использовал ‘& amp;’ и теперь работает.

    Reply
  66. 7OH

    Вопрос по существу.

    В оригинале RegExp ещё умеет возвращать массив совпадений.

    А тут только на итого проверка — иначе никак ?

    Reply
  67. starik-2005

    (66)

    А тут только на итого проверка — иначе никак ?

    Смотря чего и где искать. Для «массива совпадений» в небольшом XML может подойти XPath, реализованный в 1С для объекта DOM. Если что-то более серьезное, то иногда проще захардкодить что-то типа «А = СтрРазделить(Строка, «|»)». Но если очень охота все отдать на откуп настройщикам универсального механизма, то без RegExp никак (в Linux можно через «sed -e» или «grep» получить все, что душе угодно).

    Reply
  68. gansik

    (2) Sergey Andreev, а что Вы понимаете под «кэшированием объекта»? Как это правильно реализовать, можно примерчик? Мне как раз нужно проверять много строк на соответствие одному шаблону.

    Заранее спасибо!

    Reply
  69. gansik

    Reply
  70. starik-2005

    (68) просто добавьте в функцию параметр «test», а в коде функции строки с созданием объекта оберните в блок Если-Тогда-КонецЕсли, в котором проверяйте условие «test = неопределено». Перед первым вызовом напишите «test = Неопределено» (перед циклом проверки). В итоге у Вас функция будет вызываться только первый раз с пустым объектом XDTO, а в следующий раз уже с заполненным, что приведет к использованию уже созданного объекта, а не созданию нового.

    Reply
  71. gansik

    (70)Спасибо, всё получилось!

    Reply
  72. charivnick

    Не работают конструкции начало и конца строки: $,#k8SjZc9Dxk

    Reply
  73. starik-2005

    (72) Да, об этом написано выше.

    Reply
  74. bad_wag

    А можно ли сделать, чтобы передаешь функции строку, а она возвращает вырезанный кусок по паттерну?

    Reply
  75. starik-2005

    (74)

    А можно ли сделать

    Через XDTO нельзя. А вот через сом-объект RegExp можно (см. (66))

    Reply
  76. luckily

    (72)

    многострочный текст придется по одной строке проверять. как вариант Для Индекс=1 по СтрЧислоСтрок(Текст) Цикл

    // СтрПолучитьСтроку(Текст,Индекс) — Получает строку многострочной строки по номеру.

    Вставляем Маркер начала строки, например, знак @ и парсим начиная шаблон с него.

    СтрТекста=»@»+СтрПолучитьСтроку(Текст,Индекс);

    И наконец,

    Сообщить(ПроверитьСтроку(«СтрТекста»,»@.*»));

    Reply
  77. starik-2005

    (76)

    многострочный текст придется по одной строке проверять. как вариант Для Индекс=1 по СтрЧислоСтрок(Текст) Цикл

    Да, придется по строке. Но СтрПолучитьСтроку долго работает — лучше так:

      Для Каждого Ст ИЗ СтрРазделить ( Текст, Символы.ВС ) Цикл // разделитель подберите сами
    Сообщить ( ПроверитьСтроку ( Ст, «@.*» ) );
    КонецЦикла; 
    Reply
  78. starik-2005

    (78) предложите заголовок, который будет более информативным))

    Reply
  79. Diversus

    (0) А подскажите, как проверить с учетом кирилицы?

    Например есть строка: Купить мороженное завтра в 15:00

    Регулярное выражение: (завтра в )d{2}:d{2}



    По идее все правильно (обычно все тестирую https://regex101.com/), но вот из 1С вашим способом не работает. Как воспользоваться?

    Спасибо! Классная идея.

    PS: Вообще не совсем понятно, почему до сих пор в платформе нет нормальных регулярных выражений встроенных в платформу.

    Reply
  80. Diversus

    (80)

    (завтра в )d{2}:d{2}

    Пробовал и вот так: завтра в d{2}:d{2}

    Reply
  81. Diversus

    (80) Разобрался.

    ПроверитьСтроку(«Купить мороженное завтра в 15:00», «.*завтра в d{2}:d{2}»)

    Reply
  82. AlexeyPapanov

    Автор, ты крут!

    Очень пригодилось.

    Подскажите, а если разные строки в цикле проверять на разные фасеты, то можно ли как-то закешировать фабрикуXDTO?

    Я было хотел так сделать

    Функция ПроверитьСтрокуПоФасету(ОбъектФабрикаXDTO, Строка, Фасет)
    
    Пакет = ОбъектФабрикаXDTO.Пакеты.Получить(«sample-my-package»);
    Тест = ОбъектФабрикаXDTO.Создать(Пакет.Получить(«TestObj»));
    
    Попытка
    Тест.TestItem = Строка;
    Возврат Истина
    Исключение
    Возврат Ложь
    КонецПопытки;
    
    КонецФункции
    

    Показать

    Но у фабрики же в тексте модели XML подсовывается фасет:

    »            |<pattern>» + Фасет + «</pattern>»

    Т.е. перед циклом я не соображу как создать один раз ФабрикуXDTO, чтобы потом этот объект передавать в функцию

    ПроверитьСтрокуПоФасету(ОбъектФабрикаXDTO, Строка, Фасет)
    Reply
  83. AlexeyPapanov

    (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 = Строка;
    Возврат Истина
    Исключение
    Возврат Ложь
    КонецПопытки;
    
    КонецФункции
    

    Показать

    допустим, первый раз вызвали в цикле, фабрика создалась.

    потом вне функции перед вторым ее вызовом мы меняем переменную на Ложь, чтобы объект не создавался.

    но не пойму где его хранить с первого вызова?

    извиняюсь за тупость

    Reply
  84. starik-2005

    (84) Если разные строки на РАЗНЫЕ фасеты, то придется создать фабрику каждый раз, т.к. я, лично, не знаю способа переопределения типа в уже созданной фабрике.

    А если фасет одинаковый, то его можно и закешировать. Хранить кеш нужно в вызывающей функции.

    Reply
  85. AlexeyPapanov

    (85) Спасибо! а то я вчера поздно сидел — смотрю, один пишет — получилось. Я думаю — как?…

    Reply
  86. maxster545

    Выдаёт такую ошибку:

    Модель = ФабрикаXDTO.ПрочитатьXML(Чтение);

    по причине:

    Ошибка разбора XML: — [6,14]

    Фатальная ошибка:

    Specification mandate value for attribute jectType

    Что делаю не так?

    Reply
  87. starik-2005

    (87) Вы как пользователь — полностью игнорируете детали.

    Reply
  88. luckily

    Не указали что есть вариант использования условий:

    Вертикальная черта разделяет допустимые варианты. Например, gray|grey соответствует gray или grey

    т.е. для проверки дат «01.01.20» и 01.01.2019 может выполняться одним фасетом = «d{2}.d{2}.(d{4}|d{2})»

    Reply
  89. starik-2005

    (89) книжкой, описывающей почти все нюансы работы с регулярными выражениями, можно убить. Что Вы хотите от статьи? Почему не жалуетесь, что про группы не написано?

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *