在很多人看來,正規表示式看上去古怪且複雜,因此往往不想去觸及或使用。如果我們拋開這種「畏難」心理,在經過循序漸進地學習之後,就會發現這些複雜的表示式其實寫起來還是相當簡單的。一旦它被你所「馴服」,就可利用正規表示式把原需數小時辛苦且易錯的文字處理工作壓縮在幾分鐘(甚至幾秒鐘)內完成。
正規表示式定義
正規表示式(regular expression)是linux系統中一種非常重要的字串搜尋模式,是一組規則字元的集合。這些規則字元能夠組成我們所需要的搜尋規則,效率高、功能強,可以極大地簡化處理字串時的複雜度。在很多linux工具(sed、grep、find等)和指令碼語言(awk、perl等)中都有著重要的地位。當我們在編寫字串相關的應用程式時,掌握正規表示式會起到事半功倍的效果。
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 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()函式所得到的編譯結果。
例項說明
下面介紹如何在linux c中正確使用正規表示式,以查詢有關字串並列印出來為例:
#include
#include
#include
in chk_line(int lineno, regex_t *reg,char *line)
fprintf(stderr,"/n");
return 0;
}int chk_file(const char *filename)
rtn = regcomp(®,patten,reg_icase|reg_extended);
if(rtn)
lineno = 1;
memset(line,0,sizeof(line));
while(fgets(line,sizeof(line),fp)!= null)
fclose(fp);
regefree(®);
return 0;
}int main (int argc,char *ar**)
rtn = chk_file(ar**[1]);
return rtn;
}正規表示式示例表
字 符 意 義 示 例
* 任意長度的字串。 a* 表示: 空字串、aaaa、a…
? 長度為0或者1的字串。 a? 表示: 空字串和a。
+ 長度為乙個或者多個的字串。 a+表示:a、aa、aaaaaa…
. 任意字元。 a. 表示:a後跟任意字元。
{} 代表上一規則重複數目、
包含一組匹配花括號,裡面有兩個數字和乙個字元,表示在指定次數範圍內找到字元。 a表示:三個a、
a表示:乙個到三個a、
a 表示:大於等於三個a、
表示在3到7次重複範圍內匹配字元a。
集合,代表方括號中任意乙個字元。 [ab] 表示:a或者b都可以、
[a-z] 表示:從a到z的字元。
() 組,代表一組字元。 (ab)表示:abab。
a/b 同時滿足。 a/b表示:字串a後跟字串b才能滿足要求。
a|b 並列,代表符合a或者符合b都可以 a|b表示: 字串a或者字串b都滿足要求。
^ 如果放在開頭表示代表該規則必須在字串的開頭,其他位置代表字元本身。
如果放在中的開頭表示對該集合取反,其他位置代表字元本身。 ^a表示:a必須在字串的開頭、
[^a]表示:除了a以外的其他字元。
$ 如果放在最後表示該規則必須放在最後,其他位置代表字元本身。 a$表示:a必須在字串最後。
/:s 正規表示式用 /:s 表示空格。 a/:sb 匹配 a b。
/:a 正規表示式用 /:a 表示字元與數字。 a/:a 匹配 ab、a6 等。
/:c 正規表示式用 /:c 僅表示字元。 a/:c 匹配 ac等,不匹配a1等。
/:p 正規表示式用 /:p 表示可列印字元。
/:d 正規表示式用 /:d 僅表示數字。 a/:c 匹配 a1等,不匹配ac等。
/:x00 正規表示式用 /:x00 表示ascii字元。
/:r 正規表示式用 /:r 表示回車。
/:n 正規表示式用 /:d 表示換行。
本文重點在於闡述如何在linux c中利用正規表示式來簡化字串處理,另外linux中正規表示式內部定義了諸多內部規則來方便開發人員使用,具體含義可以檢視 man regex,相信熟悉它對你的工作會有非常大的幫助!
c語言正規表示式應用
正規表示式是能極大地提高工作效率的工具,使用過linux下各種具備re特性的工具的人一定對此深有感觸。很多語言都支援re,用的最多的當然是指令碼,其中以perl最盛。不過,用c語言來用re不是很多見,但是有時候也很有用,我最近也是看到別人說道這個,所以搜了一些資料加上自己的體會來說一說re在c語言裡...
C語言正規表示式詳解
標準的c和c 都不支援正規表示式,但有一些函式庫可以輔助c c 程式設計師完成這一功能,其中最著名的當數philip hazel的perl compatible regular expression庫,許多linux發行版本都帶有這個函式庫。c語言處理正規表示式常用的函式有regcomp regex...
C語言使用正規表示式
一 簡介 乙個好的程式設計師是會使用db和regular expression的程式設計師,可見兩者是多麼重要。正規表示式是能極大地提高工作效率的工具,使用過linux下各種具備re特性的工具的人一定對此深有感觸。很多語言都支援re,用的最多的當然是指令碼,其中以perl最盛。不過,用c語言來用re...