正则表达式的历史比C语言更来的久远,但其正式被纳入到编程语言标准中应该是在后C++时代,如JAVA、PHP、Perl等等都有各自的一套正则标准,虽然实现的形式是多样化的,但是他们解决的根本问题无非是“模式匹配”。笔者认为,正则式没有被C语言等纳入其体系中的原因正是因为自身的应用领域决定的,“模式匹配”问题在早期的C语言应用中出现的几率相对较少,我们知道在当时C语言主要用来构建操作系统等内核层,这种领域很少会遇到“模式匹配”问题,因为当时的计算问题多数跟计算机硬件打交道。而到了后期,尤其是互联网相关应用的出现,使得软件跟人的交互次数多了起来,这种交互在多数场合都是通过字符串相互传递信息的,也就是“模式匹配”问题变得多了。即便是C语言开发的应用也常常会遇到所谓“业务逻辑”等处理问题,REEC最初的设计目的是在C语言中使用正则表达式进行应用开发,使得开发人员可以方便地在C语言环境中使用正则表达式。
REEC中定义了三十六种基本的“正则模式”,一个正则模式由两部分组成:,Pat是模式串,Rep是重复次数为条件,基于Pat^Rep描述一个完整的基本模式。另外其它复杂的模式由“基本模式”组合而成,语法形式:….等等。
例如:
正则模式:<(a-z)^3> //基本模式
输入串:123123123123hello1231231231
输出串:hel
语义:匹配3个小写字母,如匹配成功返回该串。
模式:<(tok)^1><(.)^1><(com)^1>|<(net)^1>|<(cc)^1>|<(cn)^1> //多个基本模式组合
输入串:123123123123tok123tok.haha123tok123.cc1
输出串:tok.cc
语义:匹配一个由“tok”开头,紧接着“.”,以“com”或者“net”或者“cc”或者“cn”结尾的串,如匹配成功返回该串。
以上第一个正则模式比较简单,REEC中推荐这种写法,使用简短的模式可以提高运行效率,如“<(.)^1><(com)^1>”可以改写为“<(.com)^1>”。REEC中一个模式用“<...>”包围,语法逻辑上的简洁明了也是其一大特点。正则表达式的输入是一个字符串,运行结果会返回一个符合其模式的串,在REEC中方便地处理字符过滤。以上运行结果有一个问题大家可能一经发现了(见粗体),上面粗体部分的字符串“3tok123.cc1”,严格来说并不是一个网址,tok与.cc之间多了一些干扰符,有些情况我们需要过滤这些干扰符,有些情况需要将其也包含在正则模式中。在REEC 1.2.0中新加了两个参数用来区分这两种情况。
REEC 1.2.0 新特性如下:
(一)模式敏感等级
(二)正则表达式分组(稍后介绍)
“模式敏感等级”跟“正则表达式分组”是1.2.0版本新加入的,这两个新特性使得正则模式更加灵活多变。当等级为RS_LEVEL_0时,模式匹配的字符可以不连续出现,如“<(0-9)^3>”匹配三个数字,3个数字在输入字符串中出现的次序不必连续,例如,可匹配 abcd999、ab9ca9cc9d ,不可匹配 :abcd99(不足3个数字)。当等级为RS_LEVEL_1时,模式匹配的字符必须连续出现。如“<(0-9)^3>”匹配三个数字,3个数字在输入字符串中出现的次序必须连续,例如,可匹配 abcd999、不可匹配 :abcd9aa9add9。
例如:
敏感:RS_LEVEL_0
模式:<(你好)^1>
输入串:你123好
输出串:你好
敏感:RS_LEVEL_1
模式:<(你好)^1>
输入串:你123好
输出串:NULL //“你…好”中间有干扰符
正则表达式分组可能是REEC的独创功能,它使得多个正则表达式为一组,分组内部的正则表达式一次执行,最后结果作为分组的计算结果传递给下一组继续计算,直至全部分组结算完毕返回。例如“http://www.tok.cc”,先从该串中取得“tok.cc”,再从该串中取到“tok”:
模式:[<(http://www.)^1><(tok)^1><(.cc)^1>][<(tok)^1>]
敏感:RS_LEVEL_1
输入串:Our page is http://www.tok.cc !
输出串:tok
正则表达式分组允许正则表达式递归定义,就是说可以在上一组式子的匹配结果上进行n次匹配。如上例所示,首先运行正则式[<(http://www.)^1><(tok)^1><(.cc)^1>]”,然后将其匹配的结果用第二组正则式“[<(tok)^1>]”进行第n次匹配(该例子n=2),最终返回“[<(tok)^1>]”匹配的结果。
正则表达式分组格式:[…][…]…[…]
执行顺序是,首先从第一个正则组开始,直至最后一个正则组,并返回最后一个正则组的匹配结果。该特性使得客户端可以针对某一个字符流进行多次模式匹配,直到分解到最精确的结果为止。
接口:
char* TOKRegularExpressionEngineRun ( char* , char* , 敏感等级 );
char* TOKRegularExpressionEngineDestroy () ;
TOKRegularExpressionEngineRun ( “[<(http://www.)^1><(tok)^1><(.cc)^1>][<(tok)^1>]” , “http://www.tok.cc” , RS_LEVEL_1 );
//不再使用REEC时,请释放被其占用的内存。
TOKRegularExpressionEngineDestroy () ;
注释:
运算符:| 起到连接两个基本正规式的作用,逻辑或运算。例如:<(a-z)^1>|<(gtkings)^1>|<(0-9){1,*}>
例子:
//正则式:<(a-z)^3>、<(a-z)^*>、<(a-z){2,3}>、<(a-z){2,*}>
//<(a-z)^3>
//匹配3个字母,出现位置不必连续
printf(“%s/n”,TOKRegularExpressionEngineRun(“<(a-z)^3>“,”你好a我们是b突壳c开源,欢迎使用1.0我们的产品。”,RS_LEVEL_0));
//结果 abc
//匹配3个字母,出现位置必须连续
printf(“%s/n”,TOKRegularExpressionEngineRun(“<(a-z)^3>“,”你好a我们是b突壳c开源,欢迎使用1.0我们的产品。”,RS_LEVEL_1));
//不连续,结果 null
//<(a-z)^*>
//匹配所有字母,出现位置不必连续
printf(“%s/n”,TOKRegularExpressionEngineRun(“<(a-z)^*>“,”你好a我们是b突壳c开源,欢迎使用1.0我们的产品。”,RS_LEVEL_0));
//结果 abc
//匹配n个字母,出现位置必须连续
printf(“%s/n”,TOKRegularExpress