时间:2021-05-20
正则表达式,又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE)。正则表达式是使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。
在c语言中,用regcomp、regexec、regfree 和regerror处理正则表达式。处理正则表达式分三步:
函数原型
int regcomp(regex_t *preg, const char *regex, int cflags);int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);void regfree(regex_t *preg);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;}编译,输出结果:
[root@zxy regex]# ./test
result is:
Success
匹配成功。
示例二
如果我想保留匹配的结果怎么操作?那就得用到 regmatch_t 结构体了。重新改写上边代码,这时就不能用REG_NOSUB选项了,代码如下:
#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;}编译,输出结果:
[root@zxy regex]# ./test
result is:
Success
ello Wo
llo W
咦??????我明明只要一个匹配结果,为什么会打印两个出来呢???????
原来regmatch_t数组的第一个元素是有特殊意义的:它是用来保存整个正则表达式能匹配的最大子串的起始和结束偏移量。所以我们在设置regmatch_t数组个数的时候一定要记住,它的个数是最大保留结果数+1。
REG_NEWLINE、REG_NOTBOL和REG_NOTEOL
好了,基本的正则运用到此为止了,现在要开始讲讲REG_NEWLINE、REG_NOTBOL和REG_NOTEOL。很多人对这三个参数有所迷惑。我也是,昨天有人问问题,就把自己错误的理解告诉了别人,然后被大神一顿鄙视。我一直认为如果想用^和$这两个匹配模式一定要用到REG_NEWLINE这个参数,其实不然。
REG_NEWLINE
首先看下man page对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.匹配任何字符的运算符(比如.)不匹配换行('\n');
2.非匹配列表([^...])不包含一个换行符不匹配一个换行符;
3.匹配开始运算符(^)遇到空字符串立即换行,不论在执行regexec()时,eflags是否设置了REG_NOTBOL;
4.匹配结束运算符($)遇到空字符串立即换行,不论在执行regexec()时,eflags是否设置了REG_NOTEOL;
不明白说的是什么,程序测之。。
第一个问题
代码如下:
#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;}编译,运行结果如下:
[root@zxy regex]# ./test
2. Success
4. No match
结果很明显:没有加入REG_NEWLINE的匹配成功,加入的匹配不成功。就是说不加入REG_NEWLINE,任意匹配字符(.)包含'n',加入则不包含'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_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;}编译,运行结果如下:
[root@zxy regex]# ./test
2. Success
4. No match
结果说明:不加入REG_NEWLINE,在一个不包含'n'的非列表中,'n'是不被认作空白符,加入则'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_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;}编译,运行结果如下:
[root@zxy regex]# ./test
2. No match
4. Success
结果说明:不加入REG_NEWLINE,'^'是不忽略'n'的,加入REG_NEWLINE,'^'是忽略'n'的。也就是说:不加入REG_NEWLINE,以'n'开头的字符串是不能用'^'匹配,加入REG_NEWLINE,以'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_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;}编译,运行结果如下:
[root@zxy regex]# ./test
2. No match
4. Success
结果说明:不加入REG_NEWLINE,'$'是不忽略'n'的,加入REG_NEWLINE,'$'是忽略'n'的。也就是说:不加入REG_NEWLINE,以'n'结尾的字符串是不能用'$'匹配,加入REG_NEWLINE,以'n'开头的字符串是可以用'$'匹配。
REG_NEWLINE总结
好,REG_NEWLINE选项测试到此结束。总结下:
对于REG_NEWLINE选项,1.使用任意匹配符(.)时,任意匹配符不会包含'n';2.对于一个不含有'n'的非列表,会把'n'认作空白符。3.对于以'n'开头或结尾的字符串,会忽略'n'。使'^'和'$'可以使用。
REG_NOTBOL和REG_NOTEOL
现在开始说下REG_NOTBOL和REG_NOTEOL,首先看下man page对这两选项的说明:
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)继续googling。REG_NOTBOL
匹配开始操作符(^)会经常匹配失败(但是要考虑REG_NEWLINE),这个标志被用在当一个字符串的不同位置被传入到regexec()时,这个位置不应该被解释为该整个字符串的开始位置。
REG_NOTEOL
匹配结束操作符($)会经常失败(但是要考虑REG_NEWLINE)。(这个标志被用在当一个字符串的不同位置被传入到regexec()时,即使满足匹配结束作符,也不应该被解释为以某字符(串)为结束的)。
好吧,继续测试,第一个问题代码如下:
#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;}编译,运行结果如下:
[root@zxy regex]# ./test
2. Success
4. No match
结果说明:不加入REG_NOTBOL,一个字符串的不同位置是可以用'^'进行匹配,加入REG_NOTBOL,则不能进行匹配。
第二个问题,我实在理解不了了,网上介绍的全是没有经过验证的。。。。。。
总结
以上所述是小编给大家介绍的C语言中的正则表达式使用示例详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
正则表达式常用来在所有语言中搜索字符串的任何模式或文字。MongoDB还提供了正则表达式功能的字符串模式使用正则表达式$regex操作符。MongoDB使用PC
本文介绍在C#中使用匹配中文的正则表达式,包括纯中文、有中文、中文开头、中文结尾等几个正则表达式示例。在正则表达式中,中文可以通过Unicode编码来确定正则表
前言RegularExpression正则表达式,简称RegExp,常规通用的表达式,在多个开发语言中都有它的实现,可以通过正则表达式来快速的检索、匹配、查找、
之前一篇文章翻译了Perl语言中的递归正则表达式.其实不少语言中的正则都是支持递归的,例如本文要介绍的PHP正则递归.虽然,工作中最常用的正则表达式都很”正则”
感谢AKA及作者。Perl中的正则表达式正则表达式的三种形式正则表达式中的常用模式正则表达式的8大原则 正则表达式是Perl语言的一大特色,也是Perl程序中