溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

C語(yǔ)言中正則表達(dá)式如何使用

發(fā)布時(shí)間:2021-06-25 16:37:21 來(lái)源:億速云 閱讀:619 作者:Leah 欄目:編程語(yǔ)言

本篇文章給大家分享的是有關(guān)C語(yǔ)言中正則表達(dá)式如何使用,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說(shuō),跟著小編一起來(lái)看看吧。

正則表達(dá)式,又稱正規(guī)表示法、常規(guī)表示法(英語(yǔ):Regular Expression,在代碼中常簡(jiǎn)寫為regex、regexp或RE)。正則表達(dá)式是使用單個(gè)字符串來(lái)描述、匹配一系列符合某個(gè)句法規(guī)則的字符串。

在c語(yǔ)言中,用regcomp、regexec、regfree 和regerror處理正則表達(dá)式。處理正則表達(dá)式分三步:

  1. 編譯正則表達(dá)式,regcomp;  匹配正則表達(dá)式,regexec;  釋放正則表達(dá)式,regfree。

函數(shù)原型

/*函數(shù)說(shuō)明:Regcomp將正則表達(dá)式字符串regex編譯成regex_t的形式,后續(xù)regexec以此進(jìn)行搜索。參數(shù)說(shuō)明:  Preg:一個(gè)regex_t結(jié)構(gòu)體指針。  Regex:正則表達(dá)式字符串。  Cflags:是下邊四個(gè)值或者是他們的或(|)運(yùn)算。    REG_EXTENDED:使用POSIX擴(kuò)展正則表達(dá)式語(yǔ)法解釋的正則表達(dá)式。如果沒有設(shè)置,基本POSIX正則表達(dá)式語(yǔ)法。    REG_ICASE:忽略字母的大小寫。    REG_NOSUB:不存儲(chǔ)匹配的結(jié)果。    REG_NEWLINE:對(duì)換行符進(jìn)行“特殊照顧”,后邊詳細(xì)說(shuō)明。返回值:  0:表示成功編譯;  非0:表示編譯失敗,用regerror查看失敗信息*/int regcomp(regex_t *preg, const char *regex, int cflags);/*函數(shù)說(shuō)明: Regexec用來(lái)匹配正則文本。參數(shù)說(shuō)明:  Preg:由regcomp編譯好的regex_t結(jié)構(gòu)體指針,  String:要進(jìn)行正則匹配的字符串。  Nmatch:regmatch_t結(jié)構(gòu)體數(shù)組的大小  Pmatch:regmatch_t結(jié)構(gòu)體數(shù)組。用來(lái)保存匹配結(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ù)說(shuō)明:用來(lái)釋放regcomp編譯好的內(nèi)置變量。參數(shù)說(shuō)明:  Preg:由regcomp編譯好的regex_t結(jié)構(gòu)體指針。*/void regfree(regex_t *preg);/*函數(shù)說(shuō)明:Regcomp,regexec出錯(cuò)時(shí),會(huì)返回error code并且為非0,此時(shí)就可以用regerror得到錯(cuò)誤信息。參數(shù)說(shuō)明:  Errcode:Regcomp,regexec出錯(cuò)時(shí)的返回值  Preg:經(jīng)過(guò)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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "%s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str, 0, NULL, 0);  if (ret)  {    regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "%s\n", ebuff);    goto end;  }    regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "result is:\n%s\n", ebuff);end:  regfree(&reg);  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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "%s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str, 5, rm, 0);   if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "%s\n", ebuff);    goto end;  }  regerror(ret, &reg, 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(&reg);  return 0;}

編譯,輸出結(jié)果:

[root@zxy regex]# ./test result is:Successello Wollo W

  咦??????我明明只要一個(gè)匹配結(jié)果,為什么會(huì)打印兩個(gè)出來(lái)呢???????  原來(lái)regmatch_t數(shù)組的第一個(gè)元素是有特殊意義的:它是用來(lái)保存整個(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ù)有所迷惑。我也是,昨天有人問(wèn)問(wèn)題,就把自己錯(cuò)誤的理解告訴了別人,然后被大神一頓鄙視。我一直認(rèn)為如果想用^和$這兩個(gè)匹配模式一定要用到REG_NEWLINE這個(gè)參數(shù),其實(shí)不然。

REG_NEWLINE

首先看下man page對(duì)REG_NEWLINE的說(shuō)明:

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;

不明白說(shuō)的是什么,程序測(cè)之。。

第一個(gè)問(wèn)題

代碼如下:

#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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "1. %s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str, 0, NULL, 0);   regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "2. %s\n", ebuff);  cflags |= REG_NEWLINE;  ret = regcomp(&reg, reg_str, cflags);  if (ret)  {    regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "3. %s\n", ebuff);    goto end;  }  ret = regexec(&reg, test_str, 0, NULL, 0);  regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "4. %s\n", ebuff);end:  regfree(&reg);  return 0;}

  編譯,運(yùn)行結(jié)果如下:

[root@zxy regex]# ./test 2. Success4. No match

  結(jié)果很明顯:沒有加入REG_NEWLINE的匹配成功,加入的匹配不成功。就是說(shuō)不加入REG_NEWLINE,任意匹配字符(.)包含'n',加入則不包含'n'。

第二個(gè)問(wèn)題

代碼如下:

#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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "1. %s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str, 0, NULL, 0);   regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "2. %s\n", ebuff);  cflags |= REG_NEWLINE;  ret = regcomp(&reg, reg_str, cflags);  if (ret)  {    regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "3. %s\n", ebuff);    goto end;  }  ret = regexec(&reg, test_str, 0, NULL, 0);  regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "4. %s\n", ebuff);end:  regfree(&reg);  return 0;}

編譯,運(yùn)行結(jié)果如下:

[root@zxy regex]# ./test 2. Success4. No match

  結(jié)果說(shuō)明:不加入REG_NEWLINE,在一個(gè)不包含'n'的非列表中,'n'是不被認(rèn)作空白符,加入則'n'是被認(rèn)作空白符。

第三個(gè)問(wèn)題

代碼如下:

#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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "1. %s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str, 0, NULL, 0);   regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "2. %s\n", ebuff);  cflags |= REG_NEWLINE;  ret = regcomp(&reg, reg_str, cflags);  if (ret)  {    regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "3. %s\n", ebuff);    goto end;  }  ret = regexec(&reg, test_str, 0, NULL, 0);  regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "4. %s\n", ebuff);end:  regfree(&reg);  return 0;}

編譯,運(yùn)行結(jié)果如下:

[root@zxy regex]# ./test 2. No match5. Success

  結(jié)果說(shuō)明:不加入REG_NEWLINE,'^'是不忽略'n'的,加入REG_NEWLINE,'^'是忽略'n'的。也就是說(shuō):不加入REG_NEWLINE,以'n'開頭的字符串是不能用'^'匹配,加入REG_NEWLINE,以'n'開頭的字符串是可以用'^'匹配。

第四個(gè)問(wèn)題

代碼如下:

#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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "1. %s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str, 0, NULL, 0);   regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "2. %s\n", ebuff);  cflags |= REG_NEWLINE;  ret = regcomp(&reg, reg_str, cflags);  if (ret)  {    regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "3. %s\n", ebuff);    goto end;  }  ret = regexec(&reg, test_str, 0, NULL, 0);  regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "4. %s\n", ebuff);end:  regfree(&reg);  return 0;}

編譯,運(yùn)行結(jié)果如下:

[root@zxy regex]# ./test 2. No match5. Success

  結(jié)果說(shuō)明:不加入REG_NEWLINE,'&dollar;'是不忽略'n'的,加入REG_NEWLINE,'&dollar;'是忽略'n'的。也就是說(shuō):不加入REG_NEWLINE,以'n'結(jié)尾的字符串是不能用'&dollar;'匹配,加入REG_NEWLINE,以'n'開頭的字符串是可以用'&dollar;'匹配。

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)在開始說(shuō)下REG_NOTBOL和REG_NOTEOL,首先看下man page對(duì)這兩選項(xiàng)的說(shuō)明:

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è)問(wèn)題代碼如下:

#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, reg_str, cflags);  if (ret)  {      regerror(ret, &reg, ebuff, 256);    fprintf(stderr, "1. %s\n", ebuff);    goto end;  }    ret = regexec(&reg, test_str+1, 0, NULL, 0);   regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "2. %s\n", ebuff);  ret = regexec(&reg, test_str+1, 0, NULL, REG_NOTBOL);  regerror(ret, &reg, ebuff, 256);  fprintf(stderr, "4. %s\n", ebuff);end:  regfree(&reg);  return 0;}

編譯,運(yùn)行結(jié)果如下:

[root@zxy regex]# ./test 2. Success4. No match

結(jié)果說(shuō)明:不加入REG_NOTBOL,一個(gè)字符串的不同位置是可以用'^'進(jìn)行匹配,加入REG_NOTBOL,則不能進(jìn)行匹配。

以上就是C語(yǔ)言中正則表達(dá)式如何使用,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過(guò)這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI