Регулярные выражения в C++: Использование библиотеки PCRE. (pcre gcc cpp regex)
Ключевые слова: pcre , gcc , cpp , regex , (найти похожие документы )
From: webcode.ru <mail@webcode.ru. >
Date: Sun, 24 Nov 2006 17:02:14 +0000 (UTC)
Subject: Регулярные выражения в C++: Использование библиотеки PCRE.
Оригинал: http://webcode.ru/re/pcre/ http://webcode.ru/re/pcrelocale/
Поддержка регулярных выражений очень полезна в CGI-программировании.
В C++ отсутствуют встроенные механизмы для работы с ними. Разработчик,
однако, может воспользоваться библиотекой Perl Compatible Regular
Expressions (PCRE), ее исходные коды и документация находятся на сайте
http://www.pcre.org.
Установка
Дистрибутив содержит подробное описание процесса установки библиотеки
как в юникс-системах, так и под Windows. В последнем случае
потребуется предварительно немного изменить исходные файлы. После
компиляции появятся библиотеки pcre.lib и pcreposix.lib, которые
следует подключать к проектам, использующим PCRE.
Минимальная программа
Прежде всего нужно подключить заголовочный файл pcre.h.
#include <pcre.h>
Для простоты зафиксируем регулярное выражение (шаблон) и строку,
которая будет с ним сопоставлена, непосредственно в исходном тексте
программы в двух символьных массивах.
char pattern[] = "e";
char str[] = "test";
Если необходимо работать со строками на русском языке, можно
попытаться подключить соответствующую локаль. О том, как это сделать,
рассказано в статье "Локаль в PCRE".
Наконец, мы готовы скомпилировать шаблон. Для этого следует вызвать
функцию pcre_compile(). В первом аргументе нужно указать ссылку
на строку, содержащую регулярное выражение. Во втором параметре можно
указать различные атрибуты (соответствующие опциям /igms... в Perl).
Следующие два параметра возвращают расшифровку сообщения об ошибках
компиляции. В последнем аргументе ожидается NULL или ссылку на таблицу
локали. В случае успеха функция вернет указатель на структуру типа
pcre.
pcre *re;
int options = 0;
const char *error;
int erroffset;
re = pcre_compile ((char *) pattern, options, &error, &erroffset, NULL);
Примечание. Может оказаться так, что в поставку с компилятором уже
входит библиотека PCRE. Однако, конкретная реализация может отличаться
от оригинальной. В частности, некоторые популярные компиляторы
в определении функции pcre_exec() обходятся без параметра options.
Если при компиляции шаблона произошла ошибка, переменная re будет
содержать значение NULL.
if (!re){
cout << "Failed\n";
}
Если ошибки нет, можно вызывать функцию pcre_exec() для поиска
совпадений. В первом аргументе передают значение, возвращенное функций
pcre_compile(). Следующие три аргумента -- анализируемая строка,
ее длинна и смещение, начиная с которого будет обрабатываться строка.
Далее идет параметр, указывающий опции (их подробное описание
приведено в документации). В последних двух аргументах нужно указать
ссылку на массив целых чисел и его длину.
else{
int count = 0;
int ovector[30];
count = pcre_exec (re, NULL, (char *) str, 4, 0, 0, ovector, 30);
После работы функция возвратит число совпадений или отрицательное
число в случае ошибки.
if (!count){
cout << "No match\n";
Если найдены совпадения, то в массиве ovector будут записаны пары
индексов, указывающих на начало и конец совпадений. Первые два
элемента массива описывают положение всего совпавшего выражения.
Остальные пары -- положение подстрок, которые совпали с выражениями
в круглых скобках в шаблоне (это аналоги переменных вида $1 в Perl).
Размер массива индексов произволен, но он должен быть кратен трем.
Длина определяет максимальное число строк, которые можно получить при
сопоставлении с шаблоном, если в нем встретятся подстроки в круглых
скобках.
В нашем примере (шаблон e и строка test) найдется совпадение со второй
буквой в строке. Поэтому первые два элемента массива ovector содержат
числа 1 и 2, то есть указывают на совпадение, начинающееся в первой
позиции строки и заканчивающееся во второй. Индексация элементов
в символьных массивах C++ начинается с нуля.
Если шаблон содержит строку (e), в массиве ovector значимыми станут
две пары индексов, причем в этом случае они совпадут, поскольку весь
шаблон полностью заключен в круглые скобки.
Рассмотрим еще один простой пример, записав регулярное выражение
e(.)t. Шаблон совпадет с подстрокой est, а в первую переменную попадет
подстрока s. Поскольку теперь совпадение начинается с первого символа,
а длина совпавшей части равна трем, в первых двух элементах массива
ovector появятся значения 1 и 4. Следующая пара -- 2 и 3 (то есть
подстрока единичной длины, начинающаяся во второй позиции образца).
Полный код
Код простейшей программы приведен ниже. Шаблон и строка зафиксированы
в ее теле. Программа выводит только пары индексов из массива ovector.
#include <iostream.h>
#include <pcre.h>
int main(){
char pattern[] = "e";
char str[] = "test";
const unsigned char *tables = NULL;
setlocale (LC_CTYPE, (const char *) "ru.");
tables = pcre_maketables();
pcre *re;
int options = 0;
const char *error;
int erroffset;
re = pcre_compile ((char *) pattern, options, &error, &erroffset, NULL);
if (!re){
cout << "Failed\n";
}
else{
int count = 0;
int ovector[30];
count = pcre_exec (re, NULL, (char *) str, 4, 0, 0, ovector, 30);
if (!count){
cout << "No match\n";
}
else{
for (int c = 0; c < 2 * count; c += 2){
if (ovector[c] < 0){
cout << "<unset>\n";
}
else{
cout << ovector[c] << "/" << ovector[c + 1] << "\n";
}
}
}
}
return 0;
}
Каждый день специально обученный скрипт обращается к Яндексу и ищет
этот материал на других серверах.
© webcode.ru <mail@webcode.ru. >
Локаль в PCRE
Как построить локаль для правильной работы функций PCRE.
В предыдущей статье было рассказано о том, как применять библиотеку
PCRE (Perl Compatible Regular Expressions) в программах
на C++. Здесь же рассказано, как организовать работу библиотеки
с текстами на русском языке. Одна из первоочередных задач --
обеспечить правильную работу функций с игнорированием регистра
символов.
Установка локали
Если обратиться к определению функции pcre_compile(), то следует
обратить внимание на последний аргумент tableptr:
pcre* pcre_compile (const char *pattern,
int options,
const char **errptr,
int *erroffset,
const unsigned char *tableptr);
Если при вызове этой функции установить последний аргумент в NULL,
библиотека воспользуется собственной таблицей pcre_default_tables,
которая определена в файле chartables.c, в свою очередь
вкомпилированный в библиотечный модуль pcre.lib.
Настроить локаль для работы с национальным алфавитом можно как минимум
двумя способами. Во-первых, можно исправить упомянутую таблицу
до компиляции библиотеки. Второй способ более универсален, его
и рассмотрим.
Сформировать правильную таблицу локали помогает функция
pcre_maketables(). Она не требует передачи аргументов,
но <<подсознательно>> учитывает текущую локаль. Поэтому, чтобы
построить необходимую таблицу, вначале следует установить локаль
обычными средствами, доступными в программе на C++, а затем вызвать
pcre_maketables() и сохранить возвращенный результат -- указатель
на таблицу локали. Этот указатель следует передать в последнем
аргументе при вызове функции pcre_compile():
setlocale (LC_CTYPE, "Russian_Russia.1251");
const unsigned char *locale_tables = pcre_maketables();
re = pcre_compile (pattern, options, errptr, erroffset, locale_tables);
Обратите внимание на то, что после того, как построена таблица,
функции библиотеки PCRE не учитывают текущую локаль, а работают только
с этой таблицей. Это свойство можно с успехом использовать, чтобы
не нарушать работу остальных функций, пользующихся локалью.
В следующем примере строится таблица необходимой локали, а затем
устанавливается локаль, действующая ранее:
char *current = setlocale (LC_CTYPE, NULL);
char *res = setlocale (LC_CTYPE, locale_string);
if (!res) return false;
locale_tables = pcre_maketables();
setlocale (LC_CTYPE, current);
if (!locale_tables) return false;
Переменная locale_string содержит имя локали. О том, как его
построить, рассказано в статье "Локаль I".
Не следует забывать также и о том, что по окончании работы с таблицей
locale_tables ее следует удалить:
delete locale_tables;
Каждый день специально обученный скрипт обращается к Яндексу и ищет
этот материал на других серверах.
© webcode.ru <mail@webcode.ru. >
1.1 , danila (?? ), 11:44, 15/10/2008 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
не получается, однако... в точности примеру следую, но при make вываливается ошибка
main.c:(.text+0x57): undefined reference to 'pcre_compile'
main.c:(.text+0xb9): undefined reference to 'pcre_exec'
1.4 , Alexey (?? ), 23:22, 01/05/2009 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
А вот почитать следующую штукенцию: man pcre-config ?
PCRE-CONFIG(1)
NAME
pcre-config - program to return PCRE configuration
SYNOPSIS
pcre-config [--prefix] [--exec-prefix] [--version] [--libs]
[--libs-posix] [--cflags] [--cflags-posix]
Пример вызова: gcc -Wall 'pcre-config --libs' -o main main.c
1.6 , Анатолий (?? ), 03:51, 14/05/2011 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Непонятна ссылка на С++... Видно автор не в курсе, но это чисто С-ишная библиотека... Для С++ pcre есть wrapper PCRE с соответствующими классами и было бы логично использовать его. Хотя это конечно дело вкуса... Регулярные выражения это не объектные а функциональные технологии... В Си есть и класическая библиотека с урезанными возможностями. Там ничего подключать не надо. И часто её бывает достаточно. Глюк там только один, не работает символьный класс \d
2.7 , remarkes (? ), 14:46, 07/07/2011 [^ ] [^^ ] [^^^ ] [ответить ]
+ /–
может быть автор в курсе, но статья видимо рассчитывает на поиск яндекса, который игнорирует букву "C" (англ.) как "язык Си" и ищет что угодно к си не относящееся (пхп там и прочий яваскрипт). Я например на эту страницу попал, набрав "C++ регулярные выражения", разыскивая библиотеку именно для си.
а вообще, имхо, 99,9% статей и примеров якобы на С++ - чистой воды си
1.8 , wander (? ), 10:13, 30/11/2012 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
В конце статьи delete locale_tables - в корне неверно. delete - это оператор Си++, им нельзя освобождать память выделенную средствами Си. Правильно так:
pcre_free(locale_tables);
1.10 , Chepape (? ), 21:13, 11/06/2023 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
Фукнции в библиотеке написаны говнорукастыми разработчикфми. Нигде нельзя найти нормальное объяснение что фукнция возвращает что принимает. Одним словом лучше не писать код, чем писать код так.
1.11 , Chepape (? ), 21:18, 11/06/2023 [ответить ] [﹢﹢﹢ ] [ · · · ]
+ /–
count = pcre_exec (re, NULL, (char *) str, 4, 0, 0, ovector, 30);
Данное выражение не корректно,на деле приходится считывать через while до результата -1, чтобы обработать все шаблоны в строке