Blog. Just Blog

Использование библиотеки PCRE для работы с регулярными выражениями

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Использование библиотеки PCRE для работы с регулярными выражениями
Использование библиотеки PCRE для работы с регулярными выражениями

В предыдущей статье я упомянул об альтернативных инструментах для работы с регулярными выражениями. Наиболее известное из них - кроссплатформенная библиотека PCRE (Perl Compatible Regular Expressions). Библиотека абсолютно бесплатная, разрабатывается аж с 1997 года и используется во множестве серьезных проектов. Сегодня я покажу примеры использования этой библиотеки в приложениях на Ассемблере под Windows.

Готовые dll разных версий можно скачать здесь, но если есть навыки и желание, то, конечно, лучше самостоятельно собрать библиотеку из исходников с офсайта.

Теперь переходим к программированию. Для тестов возьмем уже знакомую вам строку и паттерн для извлечения адресов электронной почты.
  1. szPattern db '(([-_a-z0-9\.]+)@([-_a-z0-9\.]+\.([a-z]+)))',0
  2. szTest    db 'Please email me to mymail@gmail.com '
  3.           db 'or nospam@mail.com.ru. I am waiting!',0
Перед использованием регулярного выражения его надо предварительно скомпилировать, для этого используется функция pcre_compile. Дополнительно рекомендуется проанализировать регулярное выражение с помощью функции pcre_study, это позволит извлечь из него некоторую дополнительную информацию и в какой-то мере ускорить дальнейший поиск. Впрочем, этого можно и не делать.
  1.         ; Подготовить регулярное выражение
  2.         invoke  pcre_compile,szPattern,0,errBuff,errOff,NULL
  3.         mov     [re],eax
  4.  
  5.         ; Предобработка регулярного выражения
  6.         PCRE_STUDY_JIT_COMPILE = 0x0001
  7.         invoke  pcre_study,[re],PCRE_STUDY_JIT_COMPILE,errBuff
  8.         mov     [re_extra],eax
За все остальные действия по поиску и извлечению найденных паттернов отвечает единственная функция pcre_exec.
  1.         ; Длина исходной строки
  2.         invoke  lstrlen,szTest
  3.         mov     [dLen],eax
  4.  
  5.         ; Начальная позиция поиска в строке
  6.         mov     [offs],0
  7.  
  8.         ; Найти соответствие регулярному выражению
  9.         invoke  pcre_exec,[re],[re_extra],szTest,[dLen],\
  10.                 [offs],0,matches,MAX_CAPTURES
  11.         ; Количество найденных совпадений
  12.         mov     [rc],eax
Несколько слов о параметрах вызова этой функции. Обязательно указывается позиция, с которой начинается поиск. Дело в том, что если в строке находится несколько паттернов, соответствующих регулярному выражению, то каждое из них придется искать отдельно. Поэтому сперва ищем вхождение от самого начала строки, затем следующее вхождение с позиции, следующей за концом первого вхождения, и так далее, пока очередной поиск не завершится ошибкой. Массив matches будет принимать найденные данные. Его минимальный размер должен быть 4 DWORD'а, но если в регулярке используются субпаттерны, то придется выделять память с их учетом.

Если найдено хоть одно совпадение, то функция возвращает их количество, а массив matches заполняется парами DWORD'ов. В каждой паре первый DWORD обозначает начальную позицию найденного паттерна или субпаттерна относительно начала проверяемой строки, второй DWORD - конечную позицию. Перебирая пары по очереди, получаем все найденные результаты. Более полный код обработки регулярного выражения с субпаттернами будет следующим:
  1.         ; Начальная позиция поиска в строке
  2.         mov     [offs],0
  3.  
  4.         ; Длина исходной строки
  5.         invoke  lstrlen,szTest
  6.         mov     [dLen],eax
  7. loc_loop:
  8.         ; Найти соответствие регулярному выражению
  9.         invoke  pcre_exec,[re],[re_extra],szTest,[dLen],\
  10.                 [offs],0,matches,MAX_CAPTURES
  11.         ; Количество найденных совпадений
  12.         mov     [rc],eax
  13.  
  14.         ; Возникла ошибка?
  15.         or      eax,eax
  16.         js      loc_not_found
  17.         ; Хоть одно соответствие найдено?
  18.         jnz     loc_found
  19.  
  20. loc_not_found:
  21.         ; Больше ничего не найдено
  22.         jmp     loc_done
  23.  
  24. loc_found:
  25.         ; Смещение конца найденного паттерна
  26.         mov     ecx,[matches+4]
  27.         ; Новое начало поиска
  28.         mov     [offs],ecx
  29.         ; Смещение начала найденного паттерна
  30.         mov     esi,[matches]
  31.         ; Вычислить длину стрки
  32.         sub     ecx,esi
  33.         or      ecx,ecx
  34.         jz      loc_next
  35.  
  36.         ; Выделить найденную строку
  37.         add     esi,szTest
  38.         mov     edi,szMatch
  39.         rep     movsb
  40.         xor     eax,eax
  41.         stosb
  42.  
  43.         ; szMatch -> строка найденного паттерна
  44.  
  45.         ; Перебрать все субпаттерны
  46.         xor     ebx,ebx
  47. loc_sub:
  48.         ; Смещение конца найденного паттерна
  49.         mov     ecx,[matches+8+ebx*8+4]
  50.         ; Смещение начала найденного паттерна
  51.         mov     esi,[matches+8+ebx*8]
  52.         ; Вычислить длину стрки
  53.         sub     ecx,esi
  54.         or      ecx,ecx
  55.         jz      loc_next
  56.  
  57.         ; Выделить найденную подстроку
  58.         add     esi,szTest
  59.         mov     edi,szMatch
  60.         rep     movsb
  61.         xor     eax,eax
  62.         stosb
  63.  
  64.         ; szMatch -> строка субпаттерна
  65.  
  66.         inc     ebx
  67.         cmp     ebx,[rc]
  68.         jb      loc_sub
  69.  
  70. loc_next:
  71.         jmp     loc_loop
  72.  
  73. loc_done:
Как видите, ничего сложного с проверкой строки на соответствие регулярному выражению нет. С получением и обработкой результатов тоже все нормально. А вот функций замены найденных паттернов библиотека PCRE не предусматривает. В лучших традициях Ассемблера это придется реализовывать самостоятельно или же все-таки надо будет воспользоваться средствами VBScript Regular Expression, описанными в предыдущей статье.

В приложении пример программы с исходным текстом, которая выполняет поиск по строке с использованием регулярных выражений и библиотеки PCRE.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

PCRE.Demo.zip (160,173 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 117 | Комментариев: 0

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0074 сек.) / Память: 4.5 Mb
Наверх