LINUX.ORG.RU

Кому нужен пример использования regex???


0

0

/*
 * regex.c                                                                                                                               
 *
 * Copyright (c) 2004 Chernookiy Vitaly <cvv@email.zp.ua> & Sergey Shkonda <serg@bcs.zp.ua> & Andrew W. Nosenko <awn@bcs.zp.ua>
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
#if defined(HAVE_GNUREGEX_H)
#    include <gnuregex.h>
#elif defined(HAVE_REGEX_H)
#   include <regex.h>
#endif
*/
#include <regex.h>

#ifndef MIN
#define MIN(x,y) ((x < y) ? x : y)
#endif

#define PARSED_STRING "123,4567,898709"
/*&#251;&#193;&#194;&#204;&#207;&#206; &#210;&#207;&#218;&#208;&#193;&#210;&#211;&#201;
&#215;&#193;&#206;&#201;&#209; &#208;&#193;&#203;&#197;&#212;&#193; &#211; &#215;&#197;&#211;&#207;&#205;*/
#define	R_REGEX	"^([^,]*),([^,]*),([^,]*)$"
#define	R_FIELD1	1
#define	R_FIELD2	2
#define	R_FIELD3	3

//==========================================================================
void* safe_calloc(size_t nmemb, size_t size)
{
    char* p;

    if (!nmemb || !size)  return NULL;

    p = calloc(nmemb, size);    /* __MEM_CHECKED__ */
    if (!p)
    {
        fprintf(stderr,"not enough memory, exiting\n");
        exit(EXIT_FAILURE);
    }
    return p;
}
//==========================================================================
#define safe_free(p)   { if (p) { free(p); p = NULL; } }
//==========================================================================
static struct re_pattern_buffer* make_regex_buf(char *expr)
{
	struct re_pattern_buffer *r;
	const char	*err;

	r = (struct re_pattern_buffer*) safe_calloc(1, sizeof(*r));
	if (!r)
		return NULL;
	re_syntax_options = RE_BACKSLASH_ESCAPE_IN_LISTS | RE_CHAR_CLASSES |
		RE_NO_BK_BRACES | RE_NO_BK_PARENS | RE_NO_BK_VBAR |
		RE_INTERVALS;
	err = re_compile_pattern(expr, strlen(expr), r);
	if (err) {
		fprintf(stderr, "re_compile('%s'): %s", expr, err);
		safe_free(r);
		return NULL;
	}
	return r;
}
★★★★★

//==========================================================================
int main(){

    int	p;
    char in_buf[BUFSIZ]=PARSED_STRING;
    char out_buf1[BUFSIZ], out_buf2[BUFSIZ], out_buf3[BUFSIZ];

    struct re_pattern_buffer *r_weight; /*&#211;&#203;&#207;&#205;&#208;&#201;&#204;&#20
1;&#210;&#207;&#215;&#193;&#206;&#206;&#217;&#19
7; &#219;&#193;&#194;&#204;&#207;&#206; &#208;&#193;&#210;&#211;&#201;&#206;&#199;&#193;
*/
    struct re_registers regs;
    
    fprintf(stderr,"PARSED_STRING=%s\n",PARSED_STRING);
    fprintf(stderr,"R_WEIGHT_REGEX=%s\n",R_REGEX);

    // compile regex for data
    if ((r_weight = make_regex_buf(R_REGEX)) == NULL) { return EXIT_FAILURE; }

#define	re_cp_reg(src, var, var_len, num)                       \
	memcpy(var, src + regs.start[num],  MIN(regs.end[num]-regs.start[num], var_len-1));  \
	var[MIN(regs.end[num]-regs.start[num], var_len-1)] = 0;

    /* parse in_buf */
    memset(&regs, 0, sizeof(regs));
    p = re_match(r_weight, in_buf, strlen(in_buf), 0, &regs);
    if (p <= 0)
    {   // not matched
        fprintf(stderr,"string '%s' not match to pattern '%s'\n",in_buf,R_REGEX);
        return EXIT_FAILURE;
    }
    //&#235;&#207;&#208;&#201;&#210;&#213;&#197;&#20
5; &#210;&#197;&#218;&#213;&#204;&#216;&#212;&#193;
&#212;&#217; &#215; &#215;&#217;&#200;&#207;&#196;&#206;&#217;&#197;
 &#194;&#213;&#198;&#197;&#210;&#193;
    re_cp_reg(in_buf, out_buf1,    sizeof(out_buf1),       R_FIELD1);
    re_cp_reg(in_buf, out_buf2,    sizeof(out_buf2),       R_FIELD2);
    re_cp_reg(in_buf, out_buf3,    sizeof(out_buf3),       R_FIELD3);
    //&#208;&#197;&#222;&#193;&#212;&#193;&#197;&#20
5; &#210;&#197;&#218;&#213;&#204;&#216;&#212;&#193;
&#212;&#217; &#201;&#218; &#215;&#217;&#200;&#207;&#196;&#206;&#217;&#200;
 &#194;&#213;&#198;&#197;&#210;&#207;&#215;
    fprintf(stderr,"out_buf1=%s\n",out_buf1);
    fprintf(stderr,"out_buf2=%s\n",out_buf2);
    fprintf(stderr,"out_buf3=%s\n",out_buf3);

    safe_free(r_weight);
    return EXIT_SUCCESS;
}

cvv ★★★★★
() автор топика
Ответ на: комментарий от bugmaker

>На перле это всего одну строку занимало :D

Точнее: можно впихнуть в одну строку.

Хотя не всегда можно юзать перл. А найти подобный пример на сях мне долго не удавалось.

cvv ★★★★★
() автор топика

дядя, вы чего-то не того накрутили... может это конечно следствие gnuregex,
но в остальбном мире юзают regex(3), где regcomp, regexec и прочее...
и нету никаких re_compile_pattern, re_match и прочего безобразия...

так что это все не очень переносимо как бы...

signal11
()
Ответ на: комментарий от cvv

Да ладно, это всево-навсево шутка была, по мотивам треда про одну строчку на перле.

Интересно, а с уникожими регекспами такое сработает?

bugmaker ★★★★☆
()
Ответ на: комментарий от cvv

Круто блин... Copyright аж на троих... :))

Но, я бы воздержался от
#ifndef MIN
#define MIN(x,y) ((x < y) ? x : y)
#endif

потенциальные грабли это, если вместо x будет стоять функция.

А в этом случае
#define safe_free(p) { if (p) { free(p); p = NULL; } }
Линуксойдам советуют использовать do{ }while(0) вместо внешних скобок {}

Честно говоря, особого смысла использовать re_compile_pattern я не вижу.
Что re_compile_pattern(), что regcomp() вызывают re_compile_internal() (судя по исходникам glibc 2.3.2), но при этом по regcomp(), regexec() есть вполне внятное info.

mky ★★★★★
()
Ответ на: комментарий от signal11

>может это конечно следствие gnuregex

Если внимательно посмотреть то так оно и есть. Проект писался для возможной сборки и с regex и с gnuregex

cvv ★★★★★
() автор топика
Ответ на: комментарий от mky

>Круто блин... Copyright аж на троих... :))

Ет небольшой кусок довольно большого проекта действительно писанного троими программерами.

>Но, я бы воздержался от

>#ifndef MIN

>#define MIN(x,y) ((x < y) ? x : y)

>#endif

>потенциальные грабли это, если вместо x будет стоять функция.

здесь вы правы. так оно и есть.

>А в этом случае

>#define safe_free(p) { if (p) { free(p); p = NULL; } }

>Линуксойдам советуют использовать do{ }while(0) вместо внешних скобок {}

А почему ?? какой от етого кайф??

>честно говоря, особого смысла использовать re_compile_pattern я не вижу.

Во первых писал не я. Во вторых по всей видимости обеспечивалась совместимость с regex & gnuregex одновременно

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

> Если внимательно посмотреть то так оно и есть.

вот и посмотрите внимательно, что это нихрена не будет работать
на BSD системах.

> Проект писался для возможной сборки и с regex и с gnuregex

:)

signal11
()
Ответ на: комментарий от signal11

>> Если внимательно посмотреть то так оно и есть.

>вот и посмотрите внимательно, что это нихрена не будет работать на BSD системах.

Вобщето проект создавался под фрёй и лет 5 под ней уже проработал.

Сейчас он портируется под линукс.

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

> Вобщето проект создавался под фрёй и лет 5 под ней уже проработал.

я говорил про OpenBSD, но сейчас и во фре гляну...
будет странно если там не так...

signal11
()
Ответ на: комментарий от signal11

> будет странно если там не так...

ну дык... смотрю на 4.9:

 - есть gnuregex.h и там есть все эти re_compile_* и прочее.
 - есть regex.h в котором этого НЕТ.

так вот получпается, что на Фре у Вас HAVE_GNUREGEX_H
определено и он смотрит в gnuregex.h, а не в regex.h.

отсюда вывод: ЭТОТ КОД НЕПОРТАБЕЛЕН.

в том же Solaris этого может и не быть, как его нет в OpenBSD.

signal11
()
Ответ на: комментарий от signal11

> отсюда вывод: ЭТОТ КОД НЕПОРТАБЕЛЕН.

С точки зрения POSIX (sorry не дописал)...

Хотя на POSIX сейчас частенько кладут, в данном случае, imho,
не надо так делать. Тем более, что есть устоявшийся интерфейс
описаный в regex(3).

signal11
()
Ответ на: комментарий от signal11

благодарю.

Мне первый раз удалось найти/увидеть пример регулярных выражений на C.

На линуксе ето компилируется и нормально работает с HAVE_REGEX_H

cvv ★★★★★
() автор топика
Ответ на: комментарий от cvv

primer na regex(3):

#include <sys/types.h>
#include <regex.h>
#include <unistd.h>

int
match_regex(const u_char *buf, const char *pat)
{
        regex_t re;
        regmatch_t pmatch[1];

        if (regcomp(&re, pat, REG_EXTENDED) < 0)
                return (-1);
        res = regexec(&re, buf, 1, pmatch, 0);
        regfree(&re);
        return (res);
}

signal11
()
Ответ на: комментарий от signal11

Большое спасибо.

очень пригодится

cvv ★★★★★
() автор топика
Ответ на: комментарий от signal11

я забыл переменную res определить ;-)

она int, естественно...

signal11
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.