首页 > 程序人生 > 深入浅出C/C++中的正则表达式库(一)——GNU Regex Library

深入浅出C/C++中的正则表达式库(一)——GNU Regex Library

写在前面: 本文是面向有正则表达式基础的读者朋友的,如果你还不知道正则表达式是什么,请先到这里学习一下 😉 :http://en.wikipedia.org/wiki/Regular_expression

正则表达式(Regular Expressions),又被称为regex或regexp,是一种十分简便、灵活的文本处理工具。它可以用来精确地找出某文本中匹配某种指定规则的内容。在linux下,grep, sed, awk等工具都支持正则表达式,这些工具的存在,为我们日常的文本处理带来了极大的便利。但是,有时候,我们自己写的程序中也需要用到正则表达式来处理一些文本,这时候就需要一些正则表达式库的支持了。由于我本人是用C/C++做为主要开发语言的,所以,在本文以及接下来的几篇文章中,我将介绍几个常用的C/C++的正则表达式的库,通过我的介绍,以及对具体的使用进行举例,希望能够给读者朋友在C/C++程序中使用正则表达式时有点帮助,这将是我莫大的荣幸。

当前,据我所知,在C/C++中常用的正则表达式库有GNU Regex Library, Boost.Regex, PCRE, PCRE++。这四个库中,后面两个是有关系,其它都是各自己独立的,是不同的实现。因此我会分三次,来一一对这四个库进行介绍。今天首先介绍一下GNU Regex Library。

1. 什么是GNU正则表达式库(GNU Regex Library) ?
GNU正则表达式库是glibc(GNU C Library)的一部分,它提供与POSIX标准兼容的正则表达式匹配的接口。
这里是其主页:http://www.gnu.org/s/libc/manual/html_node/Regular-Expressions.html
下载该库点这里:gnuregex0_13

2. GNU Regex Library所提供的接口
(1)regcomp:

1
2
3
4
5
6
int regcomp(regex_t *preg, const char *pattern, int cflags)
功能:将要进行匹配的正则表达式pattern进行编译,做匹配前的准备工作
参数: preg, 输出参数,用来保存编译后的正则表达式结果
      pattern, 输入参数,传入要进行编译的正则表达式的字符串
      cflags, 输入参数,用来指定正则表达式匹配过程中的一些选项
返回值:编译成功返回0,失败返回非0的错误码

(2)regexec:

1
2
3
4
5
6
7
8
9
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], 
            int eflags)
功能:用来检测字符串string是否匹配正则表达式preg
参数: preg, 输入参数,在(1)regcomp中编译好的正则表达式规则
      string, 输入参数,用来被匹配的字符串
      nmatch, 输入参数,用来指定pmatch参数所对应的数组的长度
      pmatch, 输出参数,用来输出在string中匹配preg的具体位置
      eflag, 输入参数,用来指定正则表达式匹配过程中的一些选项
返回值: 如果string匹配preg所指定的规则,则返回0, 否则返回非0

(3)regerror:

1
2
3
4
5
6
7
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)
功能:用来把在regcompt和regexec中产生的错误码转化成字符串形式的错误信息
参数: errcode, 输入参数,在regcomp或regexec调用中返回的错误码
      preg, 输入参数,与错误码所对应的编译过的正则表达式结构
      errbuf, 输出参数,用来返回错误信息的buffer,如果buffer不够所需大小,错误信息将被截断
      errbuf_size, 输入参数,返回错误信息的buffer的大小 
返回值: 如果errbuf_size为0,那么regerror返回错误信息所需要的buffer的大小

(4)regfree:

1
2
3
4
void regfree (regex_t *preg)
功能: 用来释放由regcomp编译时生成的preg结构所占用的内存
参数: preg, 输入参数,由regcomp编译时生成的正则表达的结构指针
返回值:

3. 使用GNU Regex Library的一些注意事项
(1)regcomp与regfree必须配对使用,要不然会造成内存泄漏(类比malloc/free, new/delete)
(2)regex_t结构:把字符串形式的正则表达式编译成regex_t这样的一个结构,方便后续的匹配工作
(3)regmatch_t结构:用来表示正则表达式中字符串中匹配的位置的结构,用起始位置的偏移量来表示的
(4)flags:用来配置匹配过程中的一些选项, 指定如何匹配,具体参见:http://www.opengroup.org/onlinepubs/007908799/xsh/regcomp.html
(5)使用该库需要包含的头文件:sys/types.h和regex .h

4. GNU Regex Library使用举例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <sys /types.h>
#include <regex .h>
#include <stdio .h>
 
int main(int argc, char ** argv)
{
    if (argc != 3)
    {
        printf("Usage: %s RegexString Text\n", argv[0]);
        return 1;
    }
 
    const char * pRegexStr = argv[1];
    const char * pText = argv[2];
 
    regex_t oRegex;
    int nErrCode = 0;
    char szErrMsg[1024] = {0};
    size_t unErrMsgLen = 0;
 
    if ((nErrCode = regcomp(&oRegex, pRegexStr, 0)) == 0)
    {
        if ((nErrCode = regexec(&oRegex, pText, 0, NULL, 0)) == 0)
        {
            printf("%s matches %s\n", pText, pRegexStr);
            regfree(&oRegex);
            return 0;
        }
    }
 
    unErrMsgLen = regerror(nErrCode, &oRegex, szErrMsg, sizeof(szErrMsg));
    unErrMsgLen = unErrMsgLen < sizeof(szErrMsg) ? unErrMsgLen : sizeof(szErrMsg) - 1;
    szErrMsg[unErrMsgLen] = '\0';
    printf("ErrMsg: %s\n", szErrMsg);
 
    regfree(&oRegex);
    return 1;
}

程序测试:

1
2
3
4
5
wuzesheng@wuzesheng-ubuntu:~/Program$ gcc TestRegex.c -o Regex
wuzesheng@wuzesheng-ubuntu:~/Program$ ./Regex "http:\/\/www\..*\.com" "https://www.taobao.com"
ErrMsg: No match
wuzesheng@wuzesheng-ubuntu:~/Program$ ./Regex "http:\/\/www\..*\.com" "http://www.taobao.com"
http://www.taobao.com matches http:\/\/www\..*\.com

以上即是关于GNU Regex Library的全部内容。如果读书者朋友有什么看法可以在下面给我留言。接下来几天,我会陆续介绍前面提到的其它几个库,今天先到这里。

  1. 2010年4月2日04:06 | #1

    为什么谷歌的插入得那么骚?

  2. 2010年4月2日04:07 | #2

    doubletony :为什么谷歌的插入得那么骚?

    “插入”前面漏了“广告”两个字。。。。

  3. 2010年4月2日08:55 | #3

    @doubletony 要引导读者能点两下,这样才有的美刀赚呀~~ 😆

  4. ashdisp
    2010年6月25日01:04 | #4

    请问一下,这些编译好后都需要附带一个dll文件吗?为什么我编译好了还提示缺少dll文件??

  5. ashdisp
    2010年6月25日01:18 | #5

    能否有其他方法,连接好后,不依赖如 regex.dll pcre3.dll这些文件呢?谢谢了

  6. 2010年6月25日09:11 | #6

    @ashdisp 可以编译成.lib的静态库,然后你在编译的时候依赖静态库编译就可以了~

  7. ashdisp
    2010年6月25日15:21 | #7

    谢谢武哥的回复,我在链接静态库时又遇到了点问题,麻烦给找找原因.

    我用的是上面的gnu正则库,下载后,用gcc编译的,ar命令编译的静态库
    1.先编译成静态库
    gcc -c regex.c -o regex.o
    ar -crv libregex.a regex.o
    生成静态库libregex.a,放在当前目录下,没有放入lib目录下

    2.将regex.h放入include目录下

    3.copy了上面的测试代码放在main.c中 ,并编译main.c
    gcc -c main.c -o main.o

    4.将静态库libregex.a 和main.o 链接成目标文件
    gcc -o main.exe main.o libregex.a

    链接过程中出现问题了,总是提示 未定义的引用,也不知道这究竟是什么原因?
    libregex.a(regex.o):regex.c:(.text+0x21): undefined reference to `bzero’
    libregex.a(regex.o):regex.c:(.text+0x42eb): undefined reference to `bcopy’
    libregex.a(regex.o):regex.c:(.text+0x5dd5): undefined reference to `bcmp’

  8. 2010年6月25日15:38 | #8

    @ashdisp 最后一步: gcc -o main.exe main.o -lregex -L./, 试一下!

  9. ashdisp
    2010年6月25日21:10 | #9

    谢谢了,还是不行,又找了个库,http://www.regexlab.com/zh/mtracer/,看了下,能正常工作,还蛮不错的,不去折腾其他库了,呵呵,谢谢您啊

  10. 2010年6月25日21:17 | #10

    @ashdisp 估计是你编译的静态库有问题~~ ps: 一般linux下都装有libregex.a的,其实可以直接用的:
    gcc a.cpp -lregex -o a

  11. chengxi
    2010年10月11日15:33 | #11

    小武哥,你好,我想在windows下使用codeblock来编译linux程序,codeblock中没有regex库。我下载了gnuregex0_13 想编译一下,放在codeblock中使用。 但是编译不成功…. 请问 你那有编译好的库吗?

  1. 2010年4月3日10:30 | #1
  2. 2013年2月26日10:21 | #2
您必须在 登录 后才能发布评论.