$ gcc -o regex regex.c程序員
生成可執行文件 regex,而後匹配regex.c文件中的"char"字符串的測試以下:正則表達式
$ regex "char" < regex.cexpress
0006: static char* substr(const char*str, unsigned start, unsigned end)
$0='char'
$1='char'數組
0009: static char stbuf[256];
$0='char'數據結構
0015: int main(int argc, char** argv)
$0='char'函數
0017: char * pattern;
$0='char'工具
0019: char ebuf[128], lbuf[256];
$0='char'測試
0020: char *st=NULL;
$0='char'指針
正則表達式定義
正則表達式(regular expression)是Linux系統中一種很是重要的字符串搜索模式,是一組規則字符的集合。這些規則字符可以組成咱們所須要的搜索規則,效率高、功能強,能夠極大地簡化處理字符串時的複雜度。在不少Linux工具(sed、grep、find等)和腳本語言(awk、perl等)中都有着重要的地位。當咱們在編寫字符串相關的應用程序時,掌握正則表達式會起到事半功倍的效果。code
C中的正則表達式
標準C和C++都不支持正則表達式,可是千萬不要覺得正則表達式就只是Perl、Python、Bash等腳本語言的專利,做爲C語言程序員,用戶一樣能夠在本身的程序中運用正則表達式,只是須要一些函數庫輔助C/C++程序員來完成這一功能。許多Linux發行版本都帶有POSIX函數庫,下面我將以POSIX函數庫中的Regex系列函數來講明在Linux c下如何使用正則表達式。
首先要用Regcomp()函數對它進行編譯,將其轉化爲Regex_t結構。由於一個正則表達式須要編譯成一個特定的數據結構才能被後續的函數使用。Regcomp()函數的原型是:
int Regcomp(regex_t *preg, const char *regex, int cflags)
參數preg指向一個聲明爲regex_t的數據結構,用來保存編譯結果。參數regex爲要編譯的正則表達式字符串。參數cflags是編譯開關,編譯開關能夠控制規則生成的特性,如REG_EXTEND表明使用擴展正則表達式模式;REG_ICASE表示對規則中字符串不區分大小寫;REG_NOSUB只檢查是否有符合規則的子串。
下面匹配正則表達式,一旦用Regcomp()函數成功地編譯了正則表達式,接下來就可調用regexec()函數完成模式匹配。Regexec()函數的原型:
int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags)
函數用於在字符串(參數string)中匹配正則表達式(參數preg)。而參數nmatch和pmatch則用於把匹配結果返回給調用程序。在調用函數egexec()進行模式匹配的過程當中,可能在字符串string中會有多處與給定的正則表達式相匹配。參數pmatch用來保存這些匹配位置。參數nmatch則告訴函數regexec()最多能夠把多少個匹配結果填充到pmatch數組中。
typedef struct {
regoff_t rm_so;
regoff_t rm_eo;
} regmatch_t;
其中rm_so表示知足規則的子串在string中的起始偏移量,rm_eo表示知足規則的子串在string中的後續偏移量。當regexec成功返回時,從pmatch[0].rm_so到pmatch[0].rm_eo是第一個匹配的字符串。最後一個參數eflags決定了匹配的特性,當須要匹配的string很是大的時候能夠經過eflags來表示是不是第一行(REG_NOTBOL),或最後一行(REG_NOTEOL)。
還有一個函數是用來獲取錯誤信息的,size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size)。參數errcode是來自函數Regcomp()或regexec()的錯誤代碼,而參數preg則是由函數Regcomp()獲得的編譯結果,其目的是把格式化消息所必須的上下文提供給regerror()函數。在執行函數regerror()時,將按照參數errbuf_size指明的最大字節數。在errbuf緩衝區中填入格式化後的錯誤信息,同時返回錯誤信息的長度。
最後釋放正則表達式。不管何時,當再也不須要已經編譯過的正則表達式時,都應該調用函數regfree()將其釋放,以避免產生內存泄漏。void regfree(regex_t *preg); 函數regfree()不會返回任何結果,它僅接收一個指向regex_t數據類型的指針,這是以前調用Regcomp()函數所獲得的編譯結果。
編譯正則表達式函數
#include <sys/types.h>
#include <regex.h>
int regcomp(regex_t *preg, const char *pattern, int cflags)
typedef struct{
int reg_magic;
size_t re_nsub;
const char *re_endp'
struct re_guts *re_g;
} regex_t;
pattern 正則表達式字符串
preg regex_t類型的結構變量, 調用放置編譯結果的地方
cflags 下面一外或多個進行"或"操做的位掩碼
REG_EXTENDED 使用POSIX延伸表示語法,不然使用POSIX基本語法
REG_NOSPEC 禁用全部的元字符,即不認爲模式字符具備特殊意義
REG_ICASE 忽略大小寫
REG_NOSUB 忽略參數nmatch和pmatch
REG_NEWLINE 不對特殊字符進行比較如^ . * ? + | / [ ] ( ) < >和$
REG_PEND 編譯模式,在遇到第一個空字節時,正則表達式不會結束,正則表達式將在preg->re_endp指向的字節以前結束。 這就容許正則表達式中引入空字節
.正則表達式錯誤, 用來取得regcomp()或regexec()的錯誤緣由
/**
* errorcode 爲由regcomp()或regexec()返回的錯誤代碼
* preg 指向pattern buffer的結構指針
* errbuf 指向欲存放錯誤字符串的緩衝區, errbuf_size爲緩衝區大小
*
* 返回錯誤字符串的長度
*/
#include <sys/types.h>
#include <regex.h>
size_t regerror(int errorcode, const regex_t *preg,
char *errbuf, size_t errbuf_size);
.匹配正則表達式
#include <sys/types.h>
#include <regex.h>
/*
* 成功返回0
* 失敗返回錯誤代碼
*/
int regexec(const regex_t *preg, //指針,指向之前編譯過的並且由regcomp(3)函數初始化的正則表達式
const char *string, //要匹配的字符串
size_t nmatch, //和pmatch把參數用於把匹配的模式返回給調用程序
regmatch_t pmatch[],
int eflags); //包含由0個或以上標誌的"或"操做 (REG_NOTBO, REG_NOTEOL, REG_STARTEND)
typedef struct{
regoff_t rm_so; //符合條件的開始位置,若是值爲-1,則表明此結構並未讓regexec()使用
regoff_t rm_eo; //符合條件的結束位置 end of match offset
} regmatch_t;
參數eflags有兩種可能,可以使用OR(|)組合:
REG_NOTBOL 讓特殊字符^無做用
REG_NOTEOL 讓特殊字符$無做用
.釋放正則表達式
#include <sys/types.h>
#include <regex.h>
void regfree(regex_t *preg);
釋放regcomp已經編譯的正則表達式
.示例
int z; //Error code
regex_t reg; //Compiled regexpr
char ebuf[128]; //Error message buffer
z = regcomp(®, pattern, REG_EXTENDED);
if(z != 0 )
{
regerror(z, ®, buf, sizeof(ebuf));
printf("%s: regcomp(3)/n", ebuf);
exit(1);
}
//.....
regfree(®);