Насамперед, повинен зауважити, що ця стаття набагато перевишує мій рівень знань C. Багато з того що тут викладено зібрано з уривків з Інтернету і ще не до кінця освоєно мною. Не не вважаю себе програмістом, це скоріше для мене забава, покищо. Дуже радий, якщо хтось хто дійсно програмує на C поправить/доповнить деякі розмазані місця.Мене давно зацікавив regex.h заголовок з стандартної бібліотеки.
man 3 regex саме його описує. Він дозволяє використання POSIX регулярних виразів всередині C програм, тобто люба наша C програмка може мати цю додаткову функціональність. Якщо ви заглянете у GNU libc докумeнтацію, ви також знайдете опис цієї бібліотеки:
http://www.gnu.org/software/libc/manual/html_node/Regular-Expressions.html#Regular-ExpressionsОтже, існує 4 функції у заголовку regex.h:
int regcomp(regex_t *preg, const char *pattern, int cflags);
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
void regfree(regex_t *preg);
regcompЦя функція "компілює" регулярний вираз у
regex_t струкруру даних яку ви можете використовувати із
regexec для порівнювання із рядком. Змінна-покажчик regex_t типу
preg вказує на адресу буфера,
де зберігатиметься "скомпільований" регулярний вираз. "Скомпільований" таким чином формат оптимізовано для ефективного порівнювання, здійснюваного пізніше
regexec. Змінна-покажчик
char типу,
*pattern вказує на рядок із нульовим закінченням '\0' який власне буде скомпільовано
regcomp.
Функція
regcomp має наступні опції, вказані в кінці як cflags:
REG_EXTENDED = Extended Regular Expressions (використання розширених регулярних виразів)
REG_ICASE = Пошук незалежний від регістра (case insensitive)
REG_NOSUB = Повідомлювати лише про вдале/невдале виконання regexec().
REG_NEWLINE = Читати через нові лінії
regexecВиконує порівнювання рядків з нульовим закінченням (
char *string) із буфером шаблона отриманим від
regcomp (
regex_t *preg). Змінні
size_t nmatch та
regmatch_t pmatch[] використовуються для вказування місця знаходження співпадань. Ключами (
int eflags) для
regexec можуть бути:
REG_NOTBOL - ^ не являєтиметься вказівником початку лінії. Цей ключ використовується коли різні рядки подаються regexec і початок рядка не повинен розглядатися як початок нової лінії.
REG_NOTEOL - $ не являтиметься знаком кінця лінії
regexec повертає 0 якщо співпадання відбулося,
REG_NOMATCH, якщо ні,
REG_ENOSYS якщо фунцкія (вираз) не пістримується.
regfreeЗвільняє всю пам'ять яка використовується regexec.
Програмування.
Запам'ятате що
regcomp повинен бути викликаним першим.
У
regcomp ви завантажуєте рядок який вас цікавить, він обробляється у
regex_t внутрішню структуру,
яка потім передається
regexec для власне порівнювання із іншими рядками. Простий виклик
regcomp виглядатиме так:
regcomp(&re, "^fre{1,}", 0); /* &re і є regex_t структурою */Простий виклик regexec:
regexec(&re, "freedom", (size_t)0, NULL, 0); Це приклад
regexec завантажиться без додаткових опцій, так само як і попередній.
В кінці дуже важливо не забути звільнити пам'ять:
regfree(&re);Виклик
regerror може виглядати так:
regerror(error, &re, string, 128);Де error, це десяткове число (int змінна), що містить повернене значення від
regexec або
regcomp,
і
string, це рядок довжиною у 128 знаків.
В кінці, приклад функції, написаної із використанням викладеного вище:
#include <sys/types.h>
#include <regex.h>
int match(const char *string, char *pattern) {
int status;
regex_t re;
if(regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB) != 0)
{
return 0;
}
status = regexec(&re, string, (size_t)0, NULL, 0);
regfree(&re);
if(status != 0)
{
return 0;
}
return 1;
}