C語言正則表達式

POSIX規定了正則表達式的C語言庫函數,詳見regex(3)。我們已經學習了很多C語言庫函數的用法,讀者應該具備自己看懂man手冊的能力了。本章介紹了正則表達式在grep、sed、awk中的用法,學習要能夠舉一反三,請讀者根據regex(3)自己總結正則表達式在C語言中的用法,寫一些簡單的程序,例如驗證用戶輸入的IP地址或email地址格式是否正確。

C語言處理正則表達式常用的函數有regcomp()、regexec()、regfree()和regerror(),一般分為三個步驟,如下所示:

C語言中使用正則表達式一般分為三步:

編譯正則表達式 regcomp()

匹配正則表達式 regexec()

釋放正則表達式 regfree()

下邊是對三個函數的詳細解釋

這個函數把指定的正則表達式pattern編譯成一種特定的數據格式compiled,這樣可以使匹配更有效。函數regexec 會使用這個數據在目標文本串中進行模式匹配。執行成功返回0。

int regcomp (regex_t *compiled, const char *pattern, int cflags)
/*
是一個結構體數據類型,用來存放編譯后的正則表達式,它的成員re_nsub 用來存儲正則表達式中的子正則表達式的個數,子正則表達式就是用圓括號包起來的部分表達式。
*/regex_t pattern     //是指向我們寫好的正則表達式的指針。cflags         //有如下4個值或者是它們或運算(|)后的值:REG_EXTENDED     //以功能更加強大的擴展正則表達式的方式進行匹配。REG_ICASE         //匹配字母時忽略大小寫。REG_NOSUB         //不用存儲匹配后的結果,只返回是否成功匹配。如果設置該標志位,那么在regexec將忽略nmatch和pmatch兩個參數。REG_NEWLINE     //識別換行符,這樣'$'就可以從行尾開始匹配,'^'就可以從行的開頭開始匹配。

當我們編譯好正則表達式后,就可以用regexec 匹配我們的目標文本串了,如果在編譯正則表達式的時候沒有指定cflags的參數為REG_NEWLINE,則默認情況下是忽略換行符的,也就是把整個文本串當作一個字符串處理。

執行成功返回0。

regmatch_t 是一個結構體數據類型,在regex.h中定義:

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

成員rm_so 存放匹配文本串在目標串中的開始位置,rm_eo 存放結束位置。通常我們以數組的形式定義一組這樣的結構。因為往往我們的正則表達式中還包含子正則表達式。數組0單元存放主正則表達式位置,后邊的單元依次存放子正則表達式位置。

int regexec (regex_t *compiled, char *string, size_t nmatch, regmatch_t matchptr[], int eflags)
compiled     //是已經用regcomp函數編譯好的正則表達式。
string     //    是目標文本串。
nmatch     //    是regmatch_t結構體數組的長度。
matchptr     regmatch_//t類型的結構體數組,存放匹配文本串的位置信息。
eflags 有兩個值:
REG_NOTBOL //讓特殊字符^無作用
REG_NOTEOL //讓特殊字符$無作用

當我們使用完編譯好的正則表達式后,或者要重新編譯其他正則表達式的時候,我們可以用這個函數清空compiled指向的regex_t結構體的內容,請記住,如果是重新編譯的話,一定要先清空regex_t結構體。

void regfree (regex_t *compiled)

當執行regcomp 或者regexec 產生錯誤的時候,就可以調用這個函數而返回一個包含錯誤信息的字符串。

size_t regerror (int errcode, regex_t *compiled, char *buffer, size_t length)errcode     //是由regcomp 和 regexec 函數返回的錯誤代號。
compiled     //是已經用regcomp函數編譯好的正則表達式,這個值可以為NULL。
buffer         //指向用來存放錯誤信息的字符串的內存空間。
length         //指明buffer的長度,如果這個錯誤信息的長度大于這個值,則regerror 函數會自動截斷超出的字符串,但他仍然會返回完整的字符串的長度。所以我們可以用如下的方法先得到錯誤字符串的長度。

例如: size_t length = regerror (errcode, compiled, NULL, 0);

測試用例:

#include <sys/types.h>
#include <regex.h>
#include <stdio.h>int main(int argc, char ** argv)
{if (argc != 3) {printf("Usage: %s RegexString Text\n", argv[0]);return 1;}const char * pregexstr = argv[1];const char * ptext = argv[2];regex_t oregex;int nerrcode = 0;char szerrmsg[1024] = {0};size_t unerrmsglen = 0;if ((nerrcode = regcomp(&oregex, pregexstr, REG_EXTENDED|REG_NOSUB)) == 0) {if ((nerrcode = regexec(&oregex, ptext, 0, NULL, 0)) == 0)    {printf("%s matches %s\n", ptext, pregexstr);regfree(&oregex);return 0;}}unerrmsglen = regerror(nerrcode, &oregex, szerrmsg, sizeof(szerrmsg));unerrmsglen = unerrmsglen < sizeof(szerrmsg) ? unerrmsglen : sizeof(szerrmsg) - 1;szerrmsg[unerrmsglen] = '\0';printf("ErrMsg: %s\n", szerrmsg);regfree(&oregex);return 1;
}

匹配網址:

./a.out "http:\/\/www\..*\.com" "http://www.taobao.com"
./a.out "^[a-zA-Z0-9]+@[a-zA-Z0-9]+.[a-zA-Z0-9]+" "itcast123@itcast.com"
./a.out "\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" "itcast@qq.com"
注:\w匹配一個字符,包含下劃線

除了gnu提供的函數外,還常用PCRE處理正則,全稱是Perl Compatible Regular Ex-pressions。從名字我們可以看出PCRE庫是與Perl中正則表達式相兼容的一個正則表達式庫。PCRE是免費開源的庫,它是由C語言實現的,這里是它的官方主頁:http://www.pcre.org/,感興趣的朋友可以在這里了解更多的內容。 要得到PCRE庫,可以從這里下載:http://sourceforge.net/projects/pcre/files/

PCRE++是一個對PCRE庫的C++封裝,它提供了更加方便、易用的C++接口。這里是它的官方主頁:http://www.daemon.de/PCRE,感興趣的朋友可以在這里了解更多的內容。 要得到PCRE++庫,可以從這里下載:http://www.daemon.de/PcreDownload

另外c++中常用 boost regex。

轉載于:https://www.cnblogs.com/wanghao-boke/p/11488587.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384833.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384833.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384833.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

makefile通用版本

實際當中程序文件比較大&#xff0c;這時候對文件進行分類&#xff0c;分為頭文件、源文件、目標文件、可執行文件。也就是說通常將文件按照文件類型放在不同的目錄當中&#xff0c;這個時候的Makefile需要統一管理這些文件&#xff0c;將生產的目標文件放在目標目錄下&#xf…

Python3OS文件/方法

Python3OS文件/方法 os模塊提供了非常豐富的方法用來處理文件和目錄。 方法 描述 os.access(path,mode) 檢驗權限模式 os.chdir(path) 改變當前工作目錄 os.chflags(path,flags) 設置路徑的標記為數字標記 os.chmod(path,mode) 更改權限 os.chown(path,uid,gid) 更改…

Python3文件

open()方法 Python open()方法永于打開一個文件&#xff0c;并返回文件對象&#xff0c;并對文件進行處理過程中都需要用到這個方法&#xff0c;如果該文件無法被打開&#xff0c;則拋出OSError 注意&#xff1a;使用open()方法一定要保證關閉文件對象&#xff0c;即調用close(…

Python3輸入輸出

Python兩種輸出值的方式&#xff0c;表達式語句和print()函數。 第三種方式是使用文件對象的write()方法&#xff0c;標準輸出文件可以用sys.stdout的引用。 如果你希望輸出的形式更加多樣&#xff0c;可以使用str.fomat()函數來格式化輸出值。 如果你希望將輸出的值轉化成字符…

動態庫加載順序

1.編譯目標代碼時指定的動態庫搜索路徑&#xff1b; 2.環境變量LD_LIBRARY_PATH指定的動態庫搜索路徑&#xff1b; 3.配置文件/etc/ld.so.conf中指定的動態庫搜索路徑&#xff1b; 4.默認的動態庫搜索路徑/lib&#xff1b; 5.默認的動態庫搜索路徑/usr/lib。 轉載于:https://ww…

Python3正則表達式

正則表達式是一個特殊的字符序列&#xff0c;他能幫助你方便的檢查一個字符串是否與某種模式匹配。re.match函數 re.match嘗試從字符串的起始位置匹配一個模式&#xff0c;如果不是起始位置匹配成功的話&#xff0c;match()就返回一個none。 函數語法&#xff1a; re.match(pat…

C/C++輸入

fgets(str,n,stdin) 從鍵盤輸入一行&#xff0c;替代gets()。讀取到n-1字節時或換行符時終止&#xff0c;如果是文件的話&#xff0c;讀到文件結尾也會停止 getline(cin,str) str的類型必須是string類&#xff0c;它是C特定的字符串類&#xff0c;區別于C的char *數據類型。 ci…

strlen和sizeof的區別

C語言中沒有字符串&#xff0c;用的是字符數組來模擬字符串。 C風格的字符串時字符數組然后在末尾加0表示結尾。 在C語言中有strlen和sizeof兩個函數求字符數組的長度函數&#xff0c;他們倆的區別就是是否把最后的結束標志也加上去。 strlen是不加的&#xff0c;他表示字符串的…

shell編程練習題

求2個數之和計算1-100的和將一目錄下所有的文件的擴展名改為bak編譯當前目錄下的所有.c文件&#xff1a;打印root可以使用可執行文件數&#xff0c;處理結果: roots bins: 2306打印當前sshd的端口和進程id&#xff0c;處理結果: sshd Port&&pid: 22 5412輸出本機創建20…

shell編程題(一)

求2個數之和 #!/bin/bashfunction add {if(( $# < 2 )); thenecho "The arg int correct"elsesum$(($1$2))echo $sumfi }add 1 add 1 2 運行結果&#xff1a; exbotubuntu:~/shareWin/linux/shell$ ./sum.sh 1 2The arg int correct3 $#&#xff1a;相當于C語言…

vimset

vim ~./vimrc set nocompatible "去掉有關vi一致性模式&#xff0c;避免以前版本的bug和局限 set nu! "顯示行號 set guifontLuxi/ Mono/ 9 " 設置字體&#xff0c;字體名稱和字號 filetype on …

shell編程題(二)

計算1-100之和 #!/bin/bashsum0 for i in seq 1 100;do #符號不是單引號 是 1左邊的符號sum$[$i $sum ] done echo $sum #!/bin/bashi0 n1              #定義循環變量 while [ $n -lt 101 ];do  #循環變量小于101 i$(( $i $n))        #累加 n$(( …

vim命令大全

1. vim模式 正常模式&#xff08;按Esc或Ctrl[進入&#xff09; 左下角顯示文件名或為空 插入模式&#xff08;按i進入&#xff09; 左下角顯示--INSERT-- 可視模式&#xff08;按v進入&#xff09; 左下角顯示--VISUAL-- 替換模式&#xff08;按r或R開始&#xff09; 左下角顯…

signal()函數

函數原型 void (*signal(int sig,void(*func)(int)))(int); 指定使用sig指定的信號編號處理信號的方法。參數func指定程序可以處理信號的三種方式之一&#xff1a; l 默認處理(SIG_DFL)&#xff1a; 信號由該特定信號的默認動作處理l 忽略信號&#xff08;SIG_IGN&a…

setitimer()函數

定時器時間函數 struct itimerval&#xff1a;struct itimerval *new_value&#xff0c;其定義如下&#xff1a;struct itimerval {struct timeval it_interval; /*next value*/struct timeval it_value; /*current value*/};struct timeval {long tv_sec; /*seconds*/lonng t…

shell編程題(三)

將一目錄下所有的文件的擴展名改為bak #! /bin/bashfor i in ls domv $i ${i%%.*}.bak done ${i%%.*} 截掉一個變量字符串第一個"."以及其右側的所有字符&#xff0c;即最短前綴匹配。 #! /bin/bashdir./ #指定文件夾for file in $dir*.txt #指定文件夾下面文件類型…

VMware安裝VMwaretools

默認點擊“安裝VMware Tools&#xff08;T&#xff09;”選項下載好安裝包 下載的安裝包放在計算機的media目錄下 進入/media/ubuntu14-04/VMware Tools目錄&#xff1a; cd /media/ubuntu14-04/VMware Tools 將安裝包復制到tmp文件夾下&#xff1a; cp VMwareTools-10.0.5-322…

shell編程題(四)

編譯當前目錄下的所有.c文件 #!/bin/bashif [ $# -lt 1 ] ;then #如果輸入參數小于1則報錯 $# C語言中的argv[0] 輸入參數個數echo "Please follow up file.c!"echo "eg: ./make.sh xxx.c"exit fiif [[ $2 "debug" ]] ;then #如果第三個參數…

stat函數

int lstat(const char *path,struct stat*buf) 當文件是一個符號鏈接時&#xff0c;lstat返回的是該符號鏈接本身的信息&#xff0c;而stat返回的是該鏈接指向的文件的信息。 struct stat {dev_t st_dev; //設備號碼ino_t st_ino; //inode節點號mo…

字符串函數參數傳入傳出(字符串反轉)

/*** strstr.c ***/ #include<stdio.h> #include<string.h>//求字符串p中abcd出現的次數 //自定義函數接口完成業務函數和main函數分開 int getCount(char *mystr,char *sub,int *ncount) {int ret 0;if(mystr NULL || sub NULL || ncount NULL){ret -1;print…