学习pcre之摘录
在linux的C標準庫包含了一個正則庫,只需要引用即可引用,但是發現Linux自帶的正則庫無法使用元字符和非貪婪匹配,例如:
str: 1.1.1.1 regex: (\d*.\d*.\d*.\d*)其中的正則表達式使用了元字符\d來匹配數字,但在regex.h的正則庫中卻無法匹配。
str: \123\456\ regex:\(.+?)\其中的正則表達式使用了非貪婪匹配,但在regex.h的正則庫中卻只匹配到了"123\456".
下面是一段測試pcre正則庫的例子:
/*************************************************************************> File Name: example3.c> Author:ge.zhang > Mail: > Created Time: 2018年03月29日 星期四 12時07分18秒************************************************************************/#include<stdio.h> #include <pcre.h> #include <string.h>#define OVECCOUNT 30 /* should be a multiple of 3 */ #define EBUFLEN 128 #define BUFLEN 1024int main() {pcre *re;const char *error;int erroffset;int ovector[OVECCOUNT];int rc, i, j;char src[] = "123.123.123.123:80|1.1.1.1:88";char pattern[] = "(\\d*.\\d*.\\d*.\\d*):(\\d*)";printf("String : %s\n", src);printf("Pattern :\"%s\"\n", pattern);re = pcre_compile(pattern, 0, &error, &erroffset, NULL);if (re == NULL) {printf("PCRE compilation failed at offset %d:%s\n", erroffset, error);return 1;}char *p = src;while ((rc = pcre_exec(re, NULL, p, strlen(p), 0, 0, ovector, OVECCOUNT)) != PCRE_ERROR_NOMATCH) {printf("ovector is {");for (j=0; j<OVECCOUNT; j++) {printf(" %d, ", ovector[j]);}printf("}\n");printf("\nOK, has matched...\n\n");for (i=0;i<rc;i++) {char *substring_start = p + ovector[2*i];int substring_length = ovector[2*i+1]-ovector[2*i];char matched[1024];memset(matched, 0, 1024);strncpy(matched, substring_start, substring_length);printf("match:%s\n", matched);}printf("iamhere p is %s\n", p);p += ovector[1];printf("iamhere p+= is %s\n", p);if (!p) break;}pcre_free(re);return 0; }? ? ? 上述代碼的打印結果截圖如下:
? ? ? ? ?
? ? ? ? ?上述代碼主要用到了pcre_compile和pcre_exec兩個函數,其原型如下:
? ? ? ? ? (1) pcre_compile
pcre *pcre_compile(const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr); 功能:編譯指定的正則表達式 參數:pattern,輸入參數,將要被編譯的字符串形式的正則表達式options,輸入參數,用來指定編譯時的一些選項errptr,輸入參數,用來輸出錯誤信息erroffset,輸出參數,pattern中出錯位置的偏移量tableptr,輸入參數,用來指定字符表,一般情況用NULL,使用缺省的字符表 返回值:被編譯好的正則表達式的pcre內部表示結構? ? ? ? ? ?(2) pcre_exec
int pcre_exec(const pcre *code, const pcre_extra *extra, const char *subject, int length, int startoffset, int options, int *ovector, int ovecsize); 功能:用來檢查某個字符串是否與指定的正則表達式匹配 參數:code,輸入參數,用pcre_compile編譯好的正則表達結構的指針extra,輸入參數,用來向pcre_exec傳一些額外的數據信息的結構的指針subject,輸入參數,要被用來匹配的字符串length,輸入參數,要被用來匹配的字符串的長度startoffset,輸入參數,用來指定subject從什么位置開始被匹配的偏移量options,輸入參數,用來指定匹配過程中的一些選項ovector,輸出參數,用來返回匹配位置偏移量的數組ovecsize,輸入參數,用來返回匹配位置偏移量的數組的最大大小 返回值:匹配成功返回非負數,匹配返回負數? ? ? ? 其中ovector這個參數需要明白,如果pcre成功匹配的話,則會把匹配字符串的起止位置寫入ovector中,例如以上代碼中ovector的值如下:
? ? ? ? $1 = {??0,? 18,? 0,? 15,? 16,? 18,? 11508,? 22708,? 6,? 4096,? 2,? 1752488,? 1756584,? 1756584,? 240,? 240,? 6,? 4,? 4,? 372,? 372,? 372,? 68,? 68,? 4,? 4,? 7,? 1745352,? 16,? 0}
? ? ? ? ?由于代碼在預定義中設置最多匹配的數量為30個,所以這里列出了30個值,其實pcre_exec只匹配到了3個結果,變量rc保存的就是pcre_exec的匹配數量。那么這三個匹配結果的起止位置分別是:
0,18 = 123.123.123.123:80 0,15 = 123.123.123.123 16.18 = 80? ? ? ? ?由此可見,根據ovector中的值就可以提取匹配結果。? ? ? ? ? 另外,代碼中的正則表達式"(\d*.\d*.\d*.\d*):(\d*)"用到了兩個小括號,由于正則表達式會將一對小括號中匹配到的值保存到匹配結果中,所以這段正則表達式匹配到了三個記過,如果目的只是匹配IP地址和端口號的話,則可以去掉小括號,即"\d*.\d*.\d*.\d*:\d*",這樣就只會匹配到一個結果。
總結
- 上一篇: 读“NoSQL注入的分析和缓解”之摘录
- 下一篇: 学习“Perl基础教程:正则表达式”之摘