首页 > 代码库 > 基于linux c编程的正则表达式

基于linux c编程的正则表达式

写这个模块的目的在于更加方便的使用基于c语言的正则匹配,在做通信协议报文解析的时候,正则表达式匹配相当有效。而linux自有的正则表达式相关函数用起来相对来说还是比较麻烦。

例如,若想把字符串in中的mac地址和timeout和freetime提取出来,可以设计正则表达式为p:

<span style="font-family:Courier New;">char *in = "QueryTimesResult,MAC=00:22:33:44:55:77,timeout=1,freetime=10;00:22:33:44:55:88,timeout=0,freetime=20";
char p[] = "\\s*([A-F0-9:]+)\\s*,\\s*timeout\\s*=\\s*([0-9]+)\\s*,\\s*freetime\\s*=\\s*([0-9]+)";</span>

调用regex_match_all接口,可以把匹配结果都提取到内存块match之中;其中cell_num代表着正则表达式的分组数目,即小括号数目;match_num代表在字符串in中可以匹配正则表达式p的次数。结构体t_mbc相当重要, 代表正则表达一个分组小括号里面的内容(整数或者字符串的首地址)。

<span style="font-family:Courier New;">regex_match_all(in, p, &match, &cell_num, &match_num);</span>

所以一个match指针代表:

              0                       cell_num

match--->+-------+-------+------------+-------+

   0     | t_mbc | t_mbc | ...........| t_mbc |

         +-------+-------+------------+-------+

         |  ................................  | 

         |------------------------------------+ 

         |....................................|

         +---------------+------------+-------+

match_num| t_mbc | t_mbc | ...........| t_mbc |

         +-------+-------+------------+-------+

匹配结果放入到match中之后,就可以方便的把值拿出来使用。

在match使用完之后,需要释放内存,调用接口函数regex_free_all即可:

<span style="font-family:Courier New;">regex_free_all(void* match, int cell_num, int match_num)</span>

源代码如下:

<span style="font-family:Courier New;">#include <stdio.h>
#include <string.h>
#include <regex.h>
#include <stdlib.h>
#include <mcheck.h>

#define SUBSLEN 10  
#define EBUFLEN 128 
#define BUFLEN 1024 

#define reg_comp(a, b, c)        regcomp(a, b ,c)
#define reg_error(a, b , c, d)   regerror(a, b, c, d)
#define reg_exec(a, b, c, d, e)  regexec(a, b, c, d, e)
#define reg_free(a)			     regfree(a)	


typedef enum data_type {
	integer,
	string,
} e_dt;

/* content match in brace */
typedef struct match_brace_content {
	e_dt type;
	union {
		int  integer;
		char *string;
	} data;	
} s_mbc;

/*
 * Description: 
 * 根据正则表达式的括号数, 以及括号里面的内容, 来初始化匹配结果集模式, 暂时不支持括号嵌套的情况
 */
int init_brace_mode(char* pattern, s_mbc** out, int* found)
{
	int ret = -1, str_len = 0;
	char *stack = NULL;
	if(pattern == NULL) {
		printf("null input pointer\n");
		goto err;
	}
	
	str_len = strlen(pattern);
	stack = (char *)malloc(str_len);
	if(stack == NULL) {
		printf("no spare memory!\n");
		goto err;
	}
	
	int i, j, find_left_brace = 0, stack_top = 0, brace_pair_cnt = 0;
	s_mbc* braces = malloc(sizeof(s_mbc));
	
	for(i = 0; i < str_len; i++) {
		if(*(pattern + i) == '(') {
			find_left_brace = 1;
			continue;
		}
				
		if(*(pattern + i) == ')') {
			brace_pair_cnt++;
			stack[stack_top] = '\0';
			find_left_brace = 0;
			stack_top = 0;
			braces = realloc(braces, brace_pair_cnt * sizeof(s_mbc));
			
			/* 判断括号里面匹配的是字符串还是数字 */
			for(j = 0; j < strlen(stack); j++) {
				if(((stack[j] > 'a') && (stack[j] < 'z')) || ((stack[j] > 'A') && (stack[j] < 'Z'))) { 
					braces[brace_pair_cnt - 1].type = string;
					printf("to match string!\n");
					break;
				}
			}
			
			if(j == strlen(stack)) {
				braces[brace_pair_cnt - 1].type = integer;
				printf("to match integer!\n");
			}
			
			continue;
		}
		
		if(find_left_brace == 0) {
			continue; 
		} else {
			stack[stack_top++] = *(pattern + i);
		}
	}
	
	if(brace_pair_cnt > 0) {
		ret = 0;
		*found = brace_pair_cnt;
		*out = braces;
	} else {
		free(braces);
	}
	
err:
	if(stack != NULL) free(stack);
	return ret;
}

int regex_match_all(char *buf, char* pattern, void** match, int *cell_num, int *match_num) { 
	size_t          len;
	regex_t         re;            
	regmatch_t      subs [SUBSLEN];    
	char            matched [BUFLEN]; 
	char            errbuf  [EBUFLEN]; 
	int             err, i, find = 0, ret = -1;
	char 			*src = http://www.mamicode.com/buf; >

打印结果:

----- string: 00:22:33:44:55:77
----- integer: 1
----- integer: 10
----- string: 00:22:33:44:55:88
----- integer: 0
----- integer: 20

基于linux c编程的正则表达式