linux c 正則庫

linux c正則庫


標準的C和C++都不支持正則表達式,但是有一些函數庫提供這一功能,其中最著名的當數Philip Hazel的Perl-Compatible Regular Expression庫,許多Linux發行版本都帶有這個函數庫




3個重要的API
recomp()函數對其進行編譯,轉換爲regex_t 結構


int regcomp(regex_t *preg,const char* regex,int cflags);


參數:regex  代表要編譯的字符串   preg  是指向regex_t 的數據結構,保存編譯的結果cflags決定了正則表達式如何被處理的細節


如果函數regcomp()執行成功,並且編譯結果被正確填充到preg中後,函數將返回0,任何其它的返回結果都代表有某種錯誤產生.


一旦用regcomp()函數成功地編譯了正則表達式,接下來就可以調用regexec()函數完成模式匹配;


int regexec(const regex_t *preg,const char* string,size_t nmatch,regmatch_t pmatch[],int eflags);


typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
}regmatch_t;




參數preg指向編譯後的正則表達式,參數string是將要進行匹配的字符串,而參數nmatch和pmatch則用於把匹配結果返回給調用程序,最後一個參數eflags決定了匹配的細節。


在調用函數regexec()進行模式匹配的過程中,可能在字符串string中會有多處與給定的正則表達式相匹配,參數pmatch就是用來保存這些匹配位置的,而參數nmatch則告訴函數regexec()最多可以把多少個匹配結果填充到pmatch數組中。當regexec()函數成功返回時,從 string+pmatch[0].rm_so到string+pmatch[0].rm_eo是第一個匹配的字符串,而從 string+pmatch[1].rm_so到string+pmatch[1].rm_eo,則是第二個匹配的字符串,依此類推。


釋放正則表達式


無論什麼時候,當不再需要已經編譯過的正則表達式時,都應該調用函數regfree()將其釋放,以免產生內存泄漏。


void regfree(regex_t *preg);
函數regfree()不會返回任何結果,它僅接收一個指向regex_t數據類型的指針,這是之前調用regcomp()函數所得到的編譯結果。


如果在程序中針對同一個regex_t結構調用了多次regcomp()函數,POSIX標準並沒有規定是否每次都必須調用regfree()函數進行釋放,但建議每次調用regcomp()函數對正則表達式進行編譯後都調用一次regfree()函數,以儘早釋放佔用的存儲空間


如果調用函數regcomp()或regexec()得到的是一個非0的返回值,則表明在對正則表達式的處理過程中出現了某種錯誤,此時可以通過調用函數regerror()得到詳細的錯誤信息。


size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_terrbuf_size);




參數errcode是來自函數regcomp()或regexec()的錯誤代碼,而參數preg則是由函數regcomp()得到的編譯結果,其目的是把格式化消息所必須的上下文提供給regerror()函數。在執行函數regerror()時,將按照參數errbuf_size指明的最大字節數,在 errbuf緩衝區中填入格式化後的錯誤信息,同時返回錯誤信息的長度。


例子:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <regex.h>




static char* substr(const char* str,unsigned start,unsigned end)
{
        unsigned n = end- start;
        static char stbuf[256];
        strncpy(stbuf,str+start,n);
        stbuf[n] = '\0';
        return stbuf;
}
int main(int argc,char **argv)
{
        char *pattern;
        int x,z,lno = 0,cflags = 0;
        char ebuf[128],lbuf[256];
        regex_t reg;
        regmatch_t pm[10];
        const size_t nmatch = 10;
        pattern = argv[1];
        z = regcomp(&reg,pattern,cflags);
        if(z != 0)
        {
            regerror(z,&reg,ebuf,sizeof(ebuf));
            fprintf(stderr,"%s:pattern '%s' \n",ebuf,pattern);
            return 1;
        }
        while(fgets(lbuf,sizeof(lbuf),stdin))
        {
            ++lno;
            if((z = strlen(lbuf)) > 0 && lbuf[z-1] == '\n')
            lbuf[z-1] = 0;
            z = regexec(&reg,lbuf,nmatch,pm,0);
           if(z == REG_NOMATCH)continue;
           else if(z != 0)
           {
                   regerror (z,&reg, ebuf, sizeof (ebuf));
     fprintf (stderr, "%s: regcom('%s')\n", ebuf, lbuf);
             return 2;
                      for(x = 0;x < nmatch && pm[x].rm_so !=  -1;++x)
          {
            if(!x)
            printf("%04d:%s\n",lno,lbuf);
            printf("$%d='%s'\n",x,substr(lbuf,pm[x].rm_so,pm[x].rm_eo));


                }
        }
        regfree(&reg);
        return 0;
}
                                                                     
  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章