GNU C 規則表示式入門(轉)

post0發表於2007-08-11
GNU C 規則表示式入門(轉)[@more@]

用過Perl的朋友應該都它提供了規則表示式功能,所以使得用perl 進行文字處理非常方便。本人最近試用了一下

    GNU C 的規則表示式功能,

    發現使用起來也很簡單,只是覺得支援的不夠強大,不能夠進行文字的替換,只能進行文字的查詢,至少目前我是

    沒有發現基於規則表示式的

    文字替換功能。

    下面我就簡單的介紹一下GNU C 的規則表示式使用方法,有理解不對的地方,還請朋友們多指正。

    在GNU C 中要使用規則表示式,需要用到以下幾個函式。(定義在/usr/include/regex.h檔案中)

    * int regcomp (regex_t *compiled, const char *pattern, int cflags)

    * int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr [], int

    eflags)

    * void regfree (regex_t *compiled)

    * size_t regerror (int errcode, regex_t *compiled, char *buffer, size_t length)

    下面我就介紹分別一下這幾個函式和它用到的一些資料型別。

    1.int regcomp (regex_t *compiled, const char *pattern, int cflags)

    這個函式把指定的規則表示式pattern編譯成一種特定的資料格式compiled,這樣可以使匹配更有效。函式

    regexec 會使用這個資料在目標文

    本串中進行模式匹配。執行成功返回0。

    regex_t 是一個結構體資料型別,用來存放編譯後的規則表示式,它的成員re_nsub 用來儲存規則表示式中的子

    規則表示式的個數,子規則表

    達式就是用圓括號包起來的部分表示式。

    pattern 是指向我們寫好的規則表示式的指標。

    cflags 有如下4個值或者是它們或運算(|)後的值:

    REG_EXTENDED 以功能更加強大的擴充套件規則表示式的方式進行匹配。

    REG_ICASE 匹配字母時忽略大小寫。

    REG_NOSUB 不用儲存匹配後的結果。

    REG_NEWLINE 識別換行符,這樣'$'就可以從行尾開始匹配,'^'就可以從行的開頭開始匹配。

    2. int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr [], int

    eflags)

    當我們編譯好規則表示式後,就可以用regexec 匹配我們的目標文字串了,如果在編譯規則表示式的時候沒有指

    定cflags的引數為

    REG_NEWLINE,則預設情況下是忽略換行符的,也就是把整個文字串當作一個字串處理。執行成功返回0。

    regmatch_t 是一個結構體資料型別,成員rm_so 存放匹配文字串在目標串中的開始位置,rm_eo 存放結束位

    置。通常我們以陣列的形式定義

    一組這樣的結構。因為往往我們的規則表示式中還包含子規則表示式。陣列0單元存放主規則表示式位置,後邊的

    單元依次存放子規則表示式位

    置。

    compiled 是已經用regcomp函式編譯好的規則表示式。

    string 是目標文字串。

    nmatch 是regmatch_t結構體陣列的長度。

    matchptr regmatch_t型別的結構體陣列,存放匹配文字串的位置資訊。

    eflags 有兩個值

    REG_NOTBOL 按我的理解是如果指定了這個值,那麼'^'就不會從我們的目標串開始匹配。總之我到現在還不是很

    明白這個引數的意義,

    原文如下:

    If this bit is set, then the beginning-of-line operator doesn't match the beginning of the

    string (presumably

    because it's not the beginning of a line).If not set, then the beginning-of-line operator

    does match the beginning

    of the string.

    REG_NOTEOL 和上邊那個作用差不多,不過這個指定結束end of line。

    3. void regfree (regex_t *compiled)

    當我們使用完編譯好的規則表示式後,或者要重新編譯其他規則表示式的時候,我們可以用這個函式清空

    compiled指向的regex_t結構體的內

    容,請記住,如果是重新編譯的話,一定要先清空regex_t結構體。

    4. size_t regerror (int errcode, regex_t *compiled, char *buffer, size_t length)

    當執行regcomp 或者regexec 產生錯誤的時候,就可以呼叫這個函式而返回一個包含錯誤資訊的字串。

    errcode 是由regcomp 和 regexec 函式返回的錯誤代號。

    compiled 是已經用regcomp函式編譯好的規則表示式,這個值可以為NULL。

    buffer 指向用來存放錯誤資訊的字串的記憶體空間。

    length 指明buffer的長度,如果這個錯誤資訊的長度大於這個值,則regerror 函式會自動截斷超出的字串,

    但他仍然會返回完整的字元

    串的長度。所以我們可以用如下的方法先得到錯誤字串的長度。

    size_t length = regerror (errcode, compiled, NULL, 0);

    好了,下面來實戰一下,這樣你就會理解的更清楚了。

    ---------------------------------------------------------------

    /* regex_test.c

    * regular expression test in GNU C

    *

    * tested on redhat6.1

    * gcc regex_test.c -o regex_test

    */

    #include

    #include

    #include

    #include

    #include

    #define SUBSLEN 10

    #define EBUFLEN 128 /* error buffer length */

    #define BUFLEN 1024 /* matched buffer length */

    int

    main (int argc, char **argv)

    {

    FILE *fp;

    size_t len; /* store error message length */

    regex_t re; /* store compilned regular expression */

    regmatch_t subs[SUBSLEN]; /* store matched string position */

    char matched[BUFLEN]; /* store matched strings */

    char errbuf[EBUFLEN]; /* store error message */

    int err, i;

    char string[] = "AAAAabaaababAbAbCdCd123123 11(123){12}";

    char pattern[] = "(([0-9]+))({[0-9]+}{1})$";

    printf ("String : %s ", string);

    printf ("Pattern: "%s" ", pattern);

    /* compile regular expression */

    err = regcomp (&re, pattern, REG_EXTENDED);

    if (err)

    {

    len = regerror (err, &re, errbuf, sizeof (errbuf));

    fprintf (stderr, "error: regcomp: %s ", errbuf);

    exit (1);

    }

    printf ("Total has subexpression: %d ", re.re_nsub);

    /* execute pattern match */

    err = regexec (&re, string, (size_t)SUBSLEN, subs, 0);

    if (err == REG_NOMATCH)

    {

    fprintf (stderr, "Sorry, no match ... ");

    regfree (&re);

    exit (0);

    }

    else if (err)

    {

    len = regerror (err, &re, errbuf, sizeof (errbuf));

    fprintf (stderr, "error: regexec: %s ", errbuf);

    exit (1);

    }

    /* if no REG_NOMATCH and no error, then pattern matched */

    printf (" OK, has matched ... ");

    for (i = 0; i <= re.re_nsub; i++)

    {

    if (i == 0)

    {

    printf ("begin: %d, end: %d, ",

    subs.rm_so, subs.rm_eo);

    }

    else

    {

    printf ("subexpression %d begin: %d, end: %d, ",

    i, subs.rm_so, subs.rm_eo);

    }

    len = subs.rm_eo - subs.rm_so;

    memcpy (matched, string + subs.rm_so, len);

    matched[len] = '';

    printf ("match: %s ", matched);

    }

    regfree(&re);

    exit(0);

   

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-944546/,如需轉載,請註明出處,否則將追究法律責任。

相關文章