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

Сложный способ организовать проверку строки с помощью регулярного выражения в 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 не будет опубликован. Обязательные поля помечены *