Linux下C语言处理正则表达式——regex.h
具体函数介绍
编译正则表达式函数
int regcomp(regex_t *preg, const char *regex, int cflags);
其中preg用于保存编译后的正则表达式,regex是我们写的正则表达式。cflags标志位后面再说。
先说说regex_t结构体:
对于这个结构体而言,我们只要记住,它是编译后的正则表达式,后面的匹配是用编译后的正则表达式,这样效率更高,而不是使用我们自己写的原始的正则表达式。此外,还要知道regex_t有一个成员re_nsub,它表示“子正则表达式的个数”。所谓“子正则表达式”就是圆括号里面的正则表达式。可能还是有点懵。没关系,慢慢来!我们使用正则表达式的一个主要目的是提取满足条件的部分。比如有个字符串username=阿星&sex=女,现在我们想提取用户名,也是就“阿星”,那么我们的正则表达式应该写成: username=([^&]*)&,也就是将匹配“阿星”的正则表达式放到圆括号中,作为整个表达式的一个子表达式。后面我们执行regexec函数后,就可以得到“阿星”(后面再讲)。
再来说说cflags:
cflags 的取值有:REG_EXTENDED、REG_ICASE、REG_NOSUB和REG_NEWLINE。这四个值可以单独使用,也可以用按位与联合使用。
其中:
REG_EXTENDED:
意思是,解释正则表达式时使用扩展的正则表达式语法。POSIX规范将正则表达式的实现方法分为了两种:基本正则表达式(BRE)和扩展正则表 达式(ERE)。
BRE和ERE到底有什么区别?其实仅仅是元字符的不同!在BRE方式中,只承认^ 、$、 . 、[ 、] 、*这些是元字符,所有其他的字符都被识别为文字字符。而ERE中,则添加了(、 ) 、{ 、} 、?、 + |、等元字符(及其相关功能)。grep命令默认支持BRE,要想支持ERE需要使用-E选项。
REG_ICASE:
如果编译正则表达式时使用了这个标志,那么在用regexec()函数进行匹配时,就忽略大小写。
REG_NOSUB:
如果使用了这个选项得到的编译后的正则表达式,在被后面的regexec()函数使用时,regexec()的nmatch参数和pmatch参数将会被忽略(后面再讲)
REG_NEWLINE:
一开始我对这个标志位的理解非常模糊,网上很多人解释的也不清楚。经过我的反复试验,终于明白了。
其实REG_NEWLINE的作用就两个:
1、 使^和$有效。
2、 绝对不匹配换行符。
相信大家也都看过Linux中的man page。对于REG_NEWLINE这个标志位的解释,在man page中用了四句话。
我们先来看后两句:
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.
这两句的意思其实就是,是^匹配一行的开始位置,$匹配一行的结束位置(如果没有使用REG_NEWLINE,这两个字符将被当做普通字符)。并且使REG_NOTBOL和REG_NOTEOL无效。
举两个例子:
有字符串:
username=xinger&sex=girl&age=22 school=BIT&husband=qinger &like=study&look=pretty
如果我们没有使用REG_NEWLINE标志,那么正则表达式^school=([^&]*)将不能匹配,因为这里^被解释成了普通字符,而不是一行的开始。
如果我们加上REG_NEWLINE标志,那么将匹配成school=BIT,此时^不再是普通字符,而是匹配一行的开始。
再比如正则表达式age=([^$]*),如果没有使用REG_NEWLINE,将匹配成:
age=22 school=BIT&husband=qinger &like=study&look=pretty
还是因为$被解释成了普通字符,
比如我们在原字符串中添加一个$,变成
username=xinger&sex=girl&age=22 school=$BIT&husband=$qinger &like=study&look=pretty
那么匹配结果变成了age=22 school=,原因依然是:把$当成了普通字符。
在来看前两句:
Match-any-character operators don't match a newline.
A nonmatching list ([^...]) not containing a newline does not match a newline.
这两句的意思说白了,就是保证不匹配换行符。比如第一句,意思是匹配任意字符的元字符也不匹配新的一行(好乱呀)。什么意思呢?就是比如说点(.)本来匹配所有的字符(注意,在POSIX中点匹配所有字符!!!和我们平时学的不一样。)但是如果使用了REG_NEWLINE标志,则不匹配换行符 。
还是举个例子吧:
有字符串:
username=xinger&sex=girl&age=22 school=BIT&husband=$qinger &like=study&look=pretty
有正则表达式:sex=([^@]*),如果没有REG_NEWLINE标志,匹配结果是:
sex=girl&age=22 school=BIT&husband=$qingerr &like=study&look=pretty
因为[^@]匹配所有不是@的字符。但是如果我们加上了REG_NEWLINE,那么匹配结果为:sex=girl&age=22,原因是REG_NEWLINE保证了绝不匹配换行符!!!其实就相当于[^@ ]不加REG_NEWLINE。
在比如,有正则表达式sex=(.*),我们前面提到过:点在POSIX中匹配任意字符(’