C之正则表达式
C不直接支持正则表达式,但是有部分函数是支持的,比如sscanf
关于sscanf
这儿有个练手的程序:ref
#include <stdio.h>
int main()
{
//例1:从<sip:tom@172.18.1.133>中提取tom
const char* url = "<sip:tom@172.18.1.133>";
char uri[10] = {0};
sscanf(url, "%*[^:]:%[^@]", uri);
printf("uri:%s\n", uri);
//例2:从iios/12DDWDFF@122中提取 12DDWDFF
const char* s = "iios/12DDWDFF@122";
char buf[20];
sscanf(s, "%*[^/]/%[^@]", buf);
printf("buf:%s\n", buf);
int k;
sscanf( "AAA123BBB456" , "%*[^0-9]%i" , &k) ;
printf("%d\n",k);
return 0;
}
需要说明的是:
- 表达式中%表示选择 ,%后面的是条件,就像正常使用中的%s
- %xx% 两个%(及以上)是会段错误的,因为第一个识别结束后就不会再识别
- %*是过滤字符,而且该函数字符匹配一旦错误则会直接退出,不会再扫描后面的字符,因此字符过滤十分常用。
- 例如%x Y %x中的Y,是分隔符,可与字符串中的符号匹配
- %i,是将数字字符转换成int型数据
ref1
ref2
不难发现,该字符匹配处理规则还是正则表达式不是完全的相同的。因此C语言中实现正则表达式的匹配还是很有必要的
C-正则表达式
以下函数的组合使用,就是为了正确的在C语言中使用正则表达式。
POSIX regex functions:
regcomp
用来编译正则表达式
int regcomp(regex_t *preg, const char *regex, int cflags);
- @preg 保存编译好的正则表达式
- @regex 待编译的原始正则表达式
- @cflags 模式选择
- @return_value 成功返回0;失败返回错误码
regexec
用来匹配正则表达式所描述的模式,匹配结果用regmatch_t来描述,返回的是在母串中匹配到的下标的范围。
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags)
- @preg 编译好了的正则表达式
- @string 待匹配的原始字符串
- @nmatch 正则表达式的模式个数(总模式+子模式)
- @pmatch 数组名,保存匹配到的模式结果信息
- @eflags 标志是否匹配行首或行尾
- @return_flag 成功则返回0,失败返回REG_NOMATCH
regerror
将上面regcomp和regexec执行返回的错误码,转换成相应的错误字符串信息。
int regerror(int errcode, const regex_t *preg, char *errbuf, int errbuf_size)
- @errcode 错误码
- @preg 编译好的正则表达式
- @errbuf 保存出错信息
- @errbuf_size errbuf大小
- @return_value 返回填充到errbuf中的错误提示字符串的长度
regfree
释放preg指向的空间
void regfree(regex_t *preg);
练手
用一个正则表达式来描述一个正确的IP字符串?
模式个数 = 1 + 括号个数
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#define MAXSIZE 100
#define N 3 //模式
#define REG_IP "([0-9]{1,3})\\.[0-9]{1,3}\\.[0-9]{1,3}\\.([0-9]{1,3})"
//待查找字符串:
const char * str = "abc192.168.1.250abchauhfiouh" ;
int main()
{
regex_t* preg = (regex_t *)malloc(sizeof(regex_t));//保存编译好的正则表达式的空间
char *errbuf1 = (char *)malloc(MAXSIZE);//保存编译出错的信息1
char *errbuf2 = (char *)malloc(MAXSIZE);//保存编译出错的信息2
//1.编译正则表达式
int errorCode = regcomp(preg, REG_IP, REG_EXTENDED);//包含子模式
if(errorCode)
{
//解析错误信息
regerror(errorCode, preg, errbuf1, MAXSIZE);
//打印错误信息
printf("%s\n", errbuf1);
return -1;
}
//2.找总模式以及子模式
regmatch_t pmatch[N];
int ret = regexec(preg, str, N, pmatch, 0);
if(ret == REG_NOMATCH)
{
//解析错误信息
regerror(ret, preg, errbuf2, MAXSIZE);
//打印错误信息
printf("%s\n", errbuf1);
return -1;
}
//3.将找到的模式结果信息打印出来
for(int i = 0; i < N; i++)
{
printf("[%d, %d)\n", pmatch[i].rm_so, pmatch[i].rm_eo);
}
for(int i = 0; i < 3; i++)
{
printf("[%d, %d) :", pmatch[i].rm_so, pmatch[i].rm_eo);
int j;
for(j = pmatch[i].rm_so; j < pmatch[i].rm_eo ; j++)
{
printf("%c", *(str+j));
}
printf("\n");
}
//4.释放正则表达式的空间
regfree(preg);
return 0;
}