vlambda博客
学习文章列表

C语言pcre库的使用及验证IP地址的合法性

PCRE是一个用C语言编写的正则表达式函数库,它十分易用,同时功能也很强大,性能超过了POSIX正则表达式库和一些经典的正则表达式库,在使用PCRE库时,首先肯定是需要安装pcre的,不过一般的系统都会有自带的PCRE库。不过如果想使用最新版本的话,也可以自已下载一个安装包。或者去官网上下载http://www.pcre.org/

PCRE的常用函数简介

这里只介绍了两个常用的接口函数,另外的可通过PCRE源码文档进行了解。使用PCRE主要是使用下面介绍的这两个函数。

pcre_compile

pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr)

功能:将一个正则表达式编译成一个内部表示,在匹配多个字符串时,可以加速匹配。其同pcre_compile2功能一样只是缺少一个参数errorcodeptr。

参数说明:

pattern 正则表达式
options 为0,或者其他参数选项
errptr 出错消息
erroffset 出错位置
tableptr 指向一个字符数组的指针,可以设置为空NULL。

pcre_exec

int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize)


功能:使用编译好的模式进行匹配,采用与Perl相似的算法,返回匹配串的偏移位置。

参数说明:

code 编译好的模式
extra 指向一个pcre_extra结构体,可以为NULL
subject 需要匹配的字符串
length 匹配的字符串长度(Byte)
startoffset 匹配的开始位置
options 选项位
ovector 指向一个结果的整型数组
ovecsize 数组大小。

PCRE在C语言中实现正则表达式的解析

上述讲了上面两个PCRE函数的介绍,目的还是为了能够运用上,所以这里就先讲解下使用PCRE的过程。主要过程分三步走第一步编译正则表达式;第二匹配正则表达式;第三步释放正则表达式。

编译正则表达式

为了提高效率,在将一个字符串与正则表达式进行比较之前,首先要用pcre_compile() /pcre_compile2() 函数对它时行编译,转化成PCRE引擎能够识别的结构(struct real_pcre)。

匹配正则表达式

一旦用函数pcre_compile() /pcre_compile2()成功地编译了正则表达式,接下来就可以调用pcre_exec()函数完成模式匹配。根据正则表达式到指定的字符串中进行查找和匹配,并输出匹配的结果。

释放正则表达式

无论什么时候,当不再需要已经编译过的正则表达式时,都应该调用函数free()将其释放,以免产生内在泄漏。

常用正则表达式

校验数字的表达式


数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|[1-9][0-9]*)$
非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(\.[0-9]{1,2})?$
1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})$
正数、负数、和小数:^(\-|\+)?\d+(\.\d+)?$
有两位小数的正实数:^[0-9]+(\.[0-9]{2})?$
1~3位小数的正实数:^[0-9]+(\.[0-9]{1,3})?$
非零的正整数:^[1-9]\d*$ 或 ^([1-9][0-9]*){1,3}$ 或 ^\+?[1-9][0-9]*$
非零的负整数:^\-[1-9][]0-9"*$ 或 ^-[1-9]\d*$
非负整数:^\d+$ 或 ^[1-9]\d*|0$
非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
非负浮点数:^\d+(\.\d+)?$ 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$
非正浮点数:^((-\d+(\.\d+)?)|(0+(\.0+)?))$ 或 ^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$
正浮点数:^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$
负浮点数:^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ 或 ^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$
浮点数:^(-?\d+)(\.\d+)?$ 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$


校验字符的表达式


汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
26个英文字母组成的字符串:^[A-Za-z]+$
26个大写英文字母组成的字符串:^[A-Z]+$
26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+


校验IPV4的地址合法性


pcre_test.c


#include <stdio.h>
#include <stdlib.h>
#include <pcre.h>
#include <string.h>

#define OVERCOUNT 128
#define IP_NUM 20
/*
功能:校验IPV4的地址合法性
输出参数:地址合法则返回0,否则返回-1
*/


int check_if_ipv4_valid(char *ipv4)
{

    //利用正则表达式去判断IP地址是否合法

    pcre *re = NULL;
    int erroffset = 0;
    const char *errptr=NULL;
    int overtor[OVERCOUNT] = {0};
    // 将要被编译的字符串形式的正则表达
    char ipv4_regular_expression[] = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$";

    if ((re = pcre_compile(ipv4_regular_expression,PCRE_CASELESS,&errptr,&erroffset,NULL)) ==NULL)
    {
        return -1;
    }

    if (pcre_exec(re,NULL,ipv4,strlen(ipv4),0,0,overtor,OVERCOUNT) > 0)
    {
        return 0;
    }

    pcre_free(re);                     // 编译正则表达式re 释放内存    
    return -1;
}


int main(int argc, char **argv)
{

    char IP[IP_NUM];

    printf("Input IPADDR\n");

    fgets(IP,sizeof(IP),stdin);
    if (0 == check_if_ipv4_valid(IP))
    {  
         printf("IP legal\n");
    }
    else
    {
        printf("IP illegal\n");
    }

}

编译运行



从上面我们可以看到PCRE库的使用相对简单,首先执行pcre_compile()函数将模式编译为pcre数据结构,接下来就可以调用pcre_exec()函数完成模式匹配。根据正则表达式到指定的字符串中进行查找和匹配,并输出匹配的结果。还有要记得编译的时候要加上 -lpcre

总结

学习正则表达式的最好方法是从例子开始,理解例子之后再自己对例子进行修改,实验。还有就是,如果你不觉得正则表达式很难读写的话,不妨找一种工具对正则表达式进行测试是否正确,这是很有必要的。例如:正则测试器 Regex Tester



推荐好文