C語言中的正則表達(dá)式使用示例詳解
正則表達(dá)式,又稱正規(guī)表示法、常規(guī)表示法(英語:Regular Expression,在代碼中常簡(jiǎn)寫為regex、regexp或RE)。正則表達(dá)式是使用單個(gè)字符串來描述、匹配一系列符合某個(gè)句法規(guī)則的字符串。
在c語言中,用regcomp、regexec、regfree 和regerror處理正則表達(dá)式。處理正則表達(dá)式分三步:
- 編譯正則表達(dá)式,regcomp;
- 匹配正則表達(dá)式,regexec;
- 釋放正則表達(dá)式,regfree。
函數(shù)原型
/* 函數(shù)說明:Regcomp將正則表達(dá)式字符串regex編譯成regex_t的形式,后續(xù)regexec以此進(jìn)行搜索。 參數(shù)說明: Preg:一個(gè)regex_t結(jié)構(gòu)體指針。 Regex:正則表達(dá)式字符串。 Cflags:是下邊四個(gè)值或者是他們的或(|)運(yùn)算。 REG_EXTENDED:使用POSIX擴(kuò)展正則表達(dá)式語法解釋的正則表達(dá)式。如果沒有設(shè)置,基本POSIX正則表達(dá)式語法。 REG_ICASE:忽略字母的大小寫。 REG_NOSUB:不存儲(chǔ)匹配的結(jié)果。 REG_NEWLINE:對(duì)換行符進(jìn)行“特殊照顧”,后邊詳細(xì)說明。 返回值: 0:表示成功編譯; 非0:表示編譯失敗,用regerror查看失敗信息 */ int regcomp(regex_t *preg, const char *regex, int cflags); /* 函數(shù)說明: Regexec用來匹配正則文本。 參數(shù)說明: Preg:由regcomp編譯好的regex_t結(jié)構(gòu)體指針, String:要進(jìn)行正則匹配的字符串。 Nmatch:regmatch_t結(jié)構(gòu)體數(shù)組的大小 Pmatch:regmatch_t結(jié)構(gòu)體數(shù)組。用來保存匹配結(jié)果的子串位置。 regmatch_t結(jié)構(gòu)體定義如下 typedef struct { regoff_t rm_so; regoff_t rm_eo; } regmatch_t; rm_so,它的值如果不為-1,表示匹配的最大子串在字符串中的起始偏移量,rm_eo,表示匹配的最大字串在字符串的結(jié)束偏移量。 Eflags: REG_NOTBOL和REG_NOTEOL為兩個(gè)值之一或二者的或(|)運(yùn)算,稍后會(huì)介紹。 返回值: 0:表示成功編譯; 非0:表示編譯失敗,用regerror查看失敗信息 */ int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); /* 函數(shù)說明:用來釋放regcomp編譯好的內(nèi)置變量。 參數(shù)說明: Preg:由regcomp編譯好的regex_t結(jié)構(gòu)體指針。 */ void regfree(regex_t *preg); /* 函數(shù)說明:Regcomp,regexec出錯(cuò)時(shí),會(huì)返回error code并且為非0,此時(shí)就可以用regerror得到錯(cuò)誤信息。 參數(shù)說明: Errcode:Regcomp,regexec出錯(cuò)時(shí)的返回值 Preg:經(jīng)過Regcomp編譯的regex_t結(jié)構(gòu)體指針。 Errbuf:錯(cuò)誤信息放置的位置。 errbuf_size:錯(cuò)誤信息buff的大小。 */ size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
示例一
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { char ebuff[256]; int ret; int cflags; regex_t reg; cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB; char *test_str = "Hello World"; char *reg_str = "H.*"; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "%s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "%s\n", ebuff); goto end; } regerror(ret, ®, ebuff, 256); fprintf(stderr, "result is:\n%s\n", ebuff); end: regfree(®); return 0; }
編譯,輸出結(jié)果:
[root@zxy regex]# ./test
result is:
Success
匹配成功。
示例二
如果我想保留匹配的結(jié)果怎么操作?那就得用到 regmatch_t 結(jié)構(gòu)體了。重新改寫上邊代碼,這時(shí)就不能用REG_NOSUB選項(xiàng)了,代碼如下:
#define _GNU_SOURCE #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { int i; char ebuff[256]; int ret; int cflags; regex_t reg; regmatch_t rm[5]; char *part_str = NULL; cflags = REG_EXTENDED | REG_ICASE; char *test_str = "Hello World"; char *reg_str = "e(.*)o"; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "%s\n", ebuff); goto end; } ret = regexec(®, test_str, 5, rm, 0); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "%s\n", ebuff); goto end; } regerror(ret, ®, ebuff, 256); fprintf(stderr, "result is:\n%s\n\n", ebuff); for (i=0; i<5; i++) { if (rm[i].rm_so > -1) { part_str = strndup(test_str+rm[i].rm_so, rm[i].rm_eo-rm[i].rm_so); fprintf(stderr, "%s\n", part_str); free(part_str); part_str = NULL; } } end: regfree(®); return 0; }
編譯,輸出結(jié)果:
[root@zxy regex]# ./test
result is:
Success
ello Wo
llo W
咦??????我明明只要一個(gè)匹配結(jié)果,為什么會(huì)打印兩個(gè)出來呢???????
原來regmatch_t數(shù)組的第一個(gè)元素是有特殊意義的:它是用來保存整個(gè)正則表達(dá)式能匹配的最大子串的起始和結(jié)束偏移量。所以我們?cè)谠O(shè)置regmatch_t數(shù)組個(gè)數(shù)的時(shí)候一定要記住,它的個(gè)數(shù)是最大保留結(jié)果數(shù)+1。
REG_NEWLINE、REG_NOTBOL和REG_NOTEOL
好了,基本的正則運(yùn)用到此為止了,現(xiàn)在要開始講講REG_NEWLINE、REG_NOTBOL和REG_NOTEOL。很多人對(duì)這三個(gè)參數(shù)有所迷惑。我也是,昨天有人問問題,就把自己錯(cuò)誤的理解告訴了別人,然后被大神一頓鄙視。我一直認(rèn)為如果想用^和$這兩個(gè)匹配模式一定要用到REG_NEWLINE這個(gè)參數(shù),其實(shí)不然。
REG_NEWLINE
首先看下man page對(duì)REG_NEWLINE的說明:
REG_NEWLINE Match-any-character operators don't match a newline. A non-matching list ([^...]) not containing a newline does not match a newline. Match-beginning-of-line operator (^) matches the empty string immediately after a newline, regardless of whether eflags, the execution flags of regexec(), contains REG_NOTBOL. Match-end-of-line operator ($) matches the empty string immediately before a newline, regardless of whether eflags contains REG_NOTEOL.
我英文不好,google翻譯之。。
REG_NEWLINE
1.匹配任何字符的運(yùn)算符(比如.)不匹配換行('\n');
2.非匹配列表([^...])不包含一個(gè)換行符不匹配一個(gè)換行符;
3.匹配開始運(yùn)算符(^)遇到空字符串立即換行,不論在執(zhí)行regexec()時(shí),eflags是否設(shè)置了REG_NOTBOL;
4.匹配結(jié)束運(yùn)算符($)遇到空字符串立即換行,不論在執(zhí)行regexec()時(shí),eflags是否設(shè)置了REG_NOTEOL;
不明白說的是什么,程序測(cè)之。。
第一個(gè)問題
代碼如下:
#define _GNU_SOURCE #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { int i; char ebuff[256]; int ret; int cflags; regex_t reg; cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB; char *test_str = "Hello World\n"; char *reg_str = "Hello World."; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "1. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "2. %s\n", ebuff); cflags |= REG_NEWLINE; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "3. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "4. %s\n", ebuff); end: regfree(®); return 0; }
編譯,運(yùn)行結(jié)果如下:
[root@zxy regex]# ./test
2. Success
4. No match
結(jié)果很明顯:沒有加入REG_NEWLINE的匹配成功,加入的匹配不成功。就是說不加入REG_NEWLINE,任意匹配字符(.)包含'n',加入則不包含'n'。
第二個(gè)問題
代碼如下:
#define _GNU_SOURCE #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { int i; char ebuff[256]; int ret; int cflags; regex_t reg; cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB; char *test_str = "Hello\nWorld"; char *reg_str = "Hello[^ ]"; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "1. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "2. %s\n", ebuff); cflags |= REG_NEWLINE; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "3. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "4. %s\n", ebuff); end: regfree(®); return 0; }
編譯,運(yùn)行結(jié)果如下:
[root@zxy regex]# ./test
2. Success
4. No match
結(jié)果說明:不加入REG_NEWLINE,在一個(gè)不包含'n'的非列表中,'n'是不被認(rèn)作空白符,加入則'n'是被認(rèn)作空白符。
第三個(gè)問題
代碼如下:
#define _GNU_SOURCE #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { int i; char ebuff[256]; int ret; int cflags; regex_t reg; cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB; char *test_str = "\nHello World"; char *reg_str = "^Hello"; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "1. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "2. %s\n", ebuff); cflags |= REG_NEWLINE; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "3. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "4. %s\n", ebuff); end: regfree(®); return 0; }
編譯,運(yùn)行結(jié)果如下:
[root@zxy regex]# ./test
2. No match
4. Success
結(jié)果說明:不加入REG_NEWLINE,'^'是不忽略'n'的,加入REG_NEWLINE,'^'是忽略'n'的。也就是說:不加入REG_NEWLINE,以'n'開頭的字符串是不能用'^'匹配,加入REG_NEWLINE,以'n'開頭的字符串是可以用'^'匹配。
第四個(gè)問題
代碼如下:
#define _GNU_SOURCE #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { int i; char ebuff[256]; int ret; int cflags; regex_t reg; cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB; char *test_str = "Hello World\n"; char *reg_str = "d$"; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "1. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "2. %s\n", ebuff); cflags |= REG_NEWLINE; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "3. %s\n", ebuff); goto end; } ret = regexec(®, test_str, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "4. %s\n", ebuff); end: regfree(®); return 0; }
編譯,運(yùn)行結(jié)果如下:
[root@zxy regex]# ./test
2. No match
4. Success
結(jié)果說明:不加入REG_NEWLINE,'$'是不忽略'n'的,加入REG_NEWLINE,'$'是忽略'n'的。也就是說:不加入REG_NEWLINE,以'n'結(jié)尾的字符串是不能用'$'匹配,加入REG_NEWLINE,以'n'開頭的字符串是可以用'$'匹配。
REG_NEWLINE總結(jié)
好,REG_NEWLINE選項(xiàng)測(cè)試到此結(jié)束??偨Y(jié)下:
對(duì)于REG_NEWLINE選項(xiàng),1.使用任意匹配符(.)時(shí),任意匹配符不會(huì)包含'n';2.對(duì)于一個(gè)不含有'n'的非列表,會(huì)把'n'認(rèn)作空白符。3.對(duì)于以'n'開頭或結(jié)尾的字符串,會(huì)忽略'n'。使'^'和'$'可以使用。
REG_NOTBOL和REG_NOTEOL
現(xiàn)在開始說下REG_NOTBOL和REG_NOTEOL,首先看下man page對(duì)這兩選項(xiàng)的說明:
REG_NOTBOL The match-beginning-of-line operator always fails to match (but see the compilation flag REG_NEWLINE above) This flag may be used when different portions of a string are passed to regexec() and the beginning of the string should not be interpreted as the beginning of the line. REG_NOTEOL The match-end-of-line operator always fails to match (but see the compilation flag REG_NEWLINE above) 繼續(xù)googling。
REG_NOTBOL
匹配開始操作符(^)會(huì)經(jīng)常匹配失敗(但是要考慮REG_NEWLINE),這個(gè)標(biāo)志被用在當(dāng)一個(gè)字符串的不同位置被傳入到regexec()時(shí),這個(gè)位置不應(yīng)該被解釋為該整個(gè)字符串的開始位置。
REG_NOTEOL
匹配結(jié)束操作符($)會(huì)經(jīng)常失敗(但是要考慮REG_NEWLINE)。(這個(gè)標(biāo)志被用在當(dāng)一個(gè)字符串的不同位置被傳入到regexec()時(shí),即使?jié)M足匹配結(jié)束作符,也不應(yīng)該被解釋為以某字符(串)為結(jié)束的)。
好吧,繼續(xù)測(cè)試,第一個(gè)問題代碼如下:
#define _GNU_SOURCE #include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <regex.h> int main (void) { int i; char ebuff[256]; int ret; int cflags; regex_t reg; cflags = REG_EXTENDED | REG_ICASE | REG_NOSUB; char *test_str = "Hello World\n"; char *reg_str = "^e"; ret = regcomp(®, reg_str, cflags); if (ret) { regerror(ret, ®, ebuff, 256); fprintf(stderr, "1. %s\n", ebuff); goto end; } ret = regexec(®, test_str+1, 0, NULL, 0); regerror(ret, ®, ebuff, 256); fprintf(stderr, "2. %s\n", ebuff); ret = regexec(®, test_str+1, 0, NULL, REG_NOTBOL); regerror(ret, ®, ebuff, 256); fprintf(stderr, "4. %s\n", ebuff); end: regfree(®); return 0; }
編譯,運(yùn)行結(jié)果如下:
[root@zxy regex]# ./test
2. Success
4. No match
結(jié)果說明:不加入REG_NOTBOL
,一個(gè)字符串的不同位置是可以用'^'進(jìn)行匹配,加入REG_NOTBOL
,則不能進(jìn)行匹配。
第二個(gè)問題,我實(shí)在理解不了了,網(wǎng)上介紹的全是沒有經(jīng)過驗(yàn)證的。。。。。。
總結(jié)
以上所述是小編給大家介紹的C語言中的正則表達(dá)式使用示例詳解,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)我們網(wǎng)站的支持!
如果你覺得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
上一篇:opencv車道線檢測(cè)的實(shí)現(xiàn)方法
欄 目:C語言
下一篇:Qt學(xué)習(xí)筆記之QPalette調(diào)色板類
本文標(biāo)題:C語言中的正則表達(dá)式使用示例詳解
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/247.html
您可能感興趣的文章
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用函數(shù)刪除字符
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)式函數(shù)庫
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)數(shù)怎么表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段函數(shù)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排序法函數(shù)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段函數(shù)
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求階乘


閱讀排行
- 1C語言 while語句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹的示例代碼(圣誕
- 3利用C語言實(shí)現(xiàn)“百馬百擔(dān)”問題方法
- 4C語言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對(duì)數(shù)函數(shù)的表達(dá)式 c語言中對(duì)
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11ajax實(shí)現(xiàn)頁面的局部加載
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-10delphi制作wav文件的方法
- 01-10使用C語言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 01-10C#中split用法實(shí)例總結(jié)