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




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2026-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

37 Comments

  1. eugeniezheludkov

    блин ну почему я так невнимательно прочитал ? скачал, а ей же еще целую конфу качать нужно, 1С:Переводчик … 🙁

    Reply ↓
  2. boogie

    Она показывает механизм, который в нём заложен.

    Reply ↓
  3. Yashazz

    Без обид, но про использование встроенных в 1С регулярок уже вроде писали… А тут ни подробностей, ничего, типа «иди качай конфу».

    Reply ↓
  4. tormozit

    Слабо раскрыты преимущества и недостатки предлагаемого метода. Я всегда пользовался VBscript.RegExp, как и большинство. Неплохо бы провести сравнение по скорости, синтаксису, объектной модели, кроссплатформенности и т.д. с ним.

    Reply ↓
  5. yukon
    Платформа до сих пор не поддерживает регулярные выражения, хотя они уже стали довольно востребованной возможностью в разных языках программирования.

    Судя по всему разработчики платформы 1С не включают язык 1С в множество этих «разных языков программирования».

    Хотя пример реализации регулярок на встроенном языке это, конечно, отличный пример madskills. На 1c-dn.com есть еще реализация парсера json, и работа с биткоинами на встроенном языке.

    Reply ↓
  6. tormozit

    (5) очень хотелось бы узнать насколько медленнее оно работает.

    Reply ↓
  7. boogie

    Определённо медленнее. Замеры можете сделать самостоятельно,

    Reply ↓
  8. Yashazz

    На каких объёмах тестировали? Известно, что на достаточно больших объёмах вызов WScriptShell вешает 1С-ку. У вас «верхняя граница» известна?

    Reply ↓
  9. boogie

    Пока намертво не зависало, при желании можете эти тесты выполнить и поделиться результатом.

    Reply ↓
  10. tormozit

    (9) Вешают только кривые выражения поиска. Но ограничение по размеру обрабатываемого текста у COM объекта VBScript.RegExp действительно есть. От чего зависит не понял, но у меня оно колеблется от 20 до 40 МБ. При его срабатывании выдается ошибка 0x8007000E (E_OUTOFMEMORY)(пример тут http://devtool1c.ucoz.ru/forum/2-270-1)

    Reply ↓
  11. boogie

    Ну, кривые выражения нужно исправлять, это как кривой код в программе.

    Reply ↓
  12. Sirruf

    Это же аццки медленно будет работать!

    Reply ↓
  13. boogie

    Работает вполне терпимо, время работы зависит сложности выражения и объёма текста, журнал регистрации анализировать регулярным выражением конечно будет долго, это для регулярной работы и не стоит делать — быстрее загнать в БД и делают выборку. А если нужно разово что-то посмотреть или сделать условие проверки поля email, например, вполне. В Переводчике используется обширно для задания условий в словаре, для очистки HTML от лишних тегов, вставляемых Вордом, для поиска заголовков и картинок и др.

    Reply ↓
  14. boogie

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

    Reply ↓
  15. for_sale

    т.е. использование внешних компонент — это ограничение, а использование целой сторонней конфы — это не ограничение?

    Reply ↓
  16. boogie

    Нет конечно — она ж на встроенном языке написана.

    Reply ↓
  17. for_sale

    (17) т.е. то, что она платная, что для скачивания даже бесплатной версии нужна регистрация, что нужна интеграция её с типовым решением, если вдруг надо что-то внедрять — это всё мелочи, главное, что она написана на языке 1С? 🙂 отличная логика!

    Reply ↓
  18. boogie

    Где сказано, что она платная?

    Reply ↓
  19. boogie

    Нужно иметь лицензию на платформу.

    Reply ↓
  20. quick

    Хороший пример извращения, к сожалению неизбежного в 1С.

    Reply ↓
  21. retif

    Когда уже РегЕкспы в платформу добавят?????

    Reply ↓
  22. starik-2005

    Регулярки на встроенном языке используются для паттернов в XDTO-пакетах. Там есть офсеты. С помощью них можно как раз это легко провернуть.

    Полагаю, авторы так и сделали.

    (22) Да, включили, через офсеты в XDTO.

    Reply ↓
  23. starik-2005

    (22) retif, можно вот так сделать чисто средствами платформы проверку:

    &НаКлиенте
    Функция ПроверитьСтроку(Строка, Фасет)
    Чтение = Новый Чтение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 = Строка;
    Возврат Истина
    Исключение
    Возврат Ложь
    КонецПопытки;
    
    КонецФункции
    
    &НаКлиенте
    Процедура Модель(Команда)
    
    Сообщить(ПроверитьСтроку(«01.01.2012″,»d{2}.d{2}.d{4}»));
    Сообщить(ПроверитьСтроку(«01.01.20121″,»d{2}.d{2}.d{4}»));
    
    КонецПроцедуры
    

    Показать

    Reply ↓
  24. artbear

    (24) Прикольная тема, сработало!

    Reply ↓
  25. artbear

    (23) Еще что интересного про ХДТО знаешь? поделись, пожалуйста.

    Reply ↓
  26. starik-2005

    (26) artbear, ну а что там надо знать-то? В моем коде просто создается фабрика на основе загруженной их XML модели, в которой определен тип с фасетом (шаблоном, задаваемым регулярным выражением), а потом при присваивании значения полю с данным типом платформа неявно вызывает проверку. В результате или все хорошо — и возвращаем истину, или все плохо возвращаем ложь. Как выгрузить модель в XDTO написано в статье «XDTO часть 3» — поиск Вам поможет.

    Reply ↓
  27. morfeus

    В статье написано что методика не использует COM объекты, а в конфигурации «Переводчик» идёт создание COM объекта. Кругом обман

    Reply ↓
  28. morfeus

    Ааа, неправ. Или ComОбъект, или кодом 1с-ным сделали. Сорри )

    Reply ↓
  29. pvlunegov

    (24) Проверка на соответствие регулярному выражению эта верхушка айсберга.

    Главные функции и задачи работы с регулярными выражениями:

    1. Получение всех подстрок тестируемой строки, удовлетворяющих регулярной строке

    2. Таких подстрок может быть множество, они могут быть вложенными одна в другую, даже иметь хаотическую вложенность в зависимости от сложности текста.

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

    Reply ↓
  30. starik-2005

    (30)

    XDTO такие задачи решить не может

    Не может — увы и ах…

    Reply ↓
  31. KAV2

    (24) Бывает нужна не проверка, а именно результат применения регулярного выражения, причем желательно с группами (в виде массива). В сабжевой функции это сделано. Не подскажете как такое же сделать с помощью фабрики XDTO?

    Reply ↓
  32. starik-2005

    (32) см (31)

    Reply ↓
  33. tunesoft

    Неоднозначная статья и комментарии.

    В мобильном приложении 1С эта методика будет работать ?

    Reply ↓
  34. boogie

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

    Reply ↓
  35. tvm

    подскажите а как с помощью (24) можно проверить наличие строке «@ » и «.» ?

    проверяемая строка например «@yandex.ru». На https://regex101.com/ шаблон вида «[@].+.+w» срабатывает норм. А здесь не получается

    Reply ↓
  36. starik-2005

    (36) «w+@w+.w+» — это если мыло, как вариант.

    Reply ↓
  37. tvm

    (37) спасибо

    Reply ↓

Leave a Comment

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