优美的舞姿--探索正则表达式(一):字符组、量词初步

前几天看《编译与反编译原理》,词法分析器的编写用到了正则表达式;以前写爬虫,对获取到的庞大的数据进一步地筛选,提取有用信息,也是离不开正则表达式。一直以来对正则都是一知半解,这几天,读了余晟老师写的《正则指引》,颇有心得,取其主干和精彩处总结一下,权当自己复习。

正则表达式,又称为规则表达式,英语是Regular Expression,所以常常简写为RE。最早是用在unix指令sed和grep里。Grep,G、re、p,中间的re正是指正则表达式。

认识正则表达式的第一步,是认识字符组。它表示在同一位置可能出现的各种字符。常常包含在一对方括号[]之间。而方括号中的内容则表示要匹配的内容。如[123]则匹配数字1,2,3。[a,b,c,d,e,f,g]则匹配字母a,b,c,d,e,f,g。

那么当要匹配的范围扩大,比如要匹配所有的字母,总不能把所有的单词全部写一遍吧。我们知道,每个ASCII字符都能对应一个ASCII码。所以,我们只需要按照ASCII码的顺序并结合‘-’符号构造一个范围表达式,如[0-9]就代表所有的数字,[a-zA-Z]就代表所有的英文大小写字母。然而当‘-’符号并不是作为两个ASCII字符的连接符时,则保持原有的意思,如[-09]代表匹配数字0,9以及符号‘-’。

如果我们要匹配不为A的所有字符呢?这时候用一个排除型字符组就可以解决。排除型字符组和普通字符组最大的不同是含有一个脱字符‘^’,如,不含A的所有字符可以表示为[^A]。

正则表达式的字符组本质上是一个集合,所以可以进行集合的运算。如,进一步,我想匹配不为F的所有大写字母,则可以写作[A-Z-[\^F]],即从A-Z匹配到的大写字母的集合里面,进行差集运算,减掉字母F。

特殊字符组:POSIX字符组。以及PCRE简记法。如[0-9]在POSIX字符组里面可以表示为[:digit:],在PCRE里面简记为\d。常用的简记还有\s(空白字符),\w(字母字符)。

而简记法字符的排除型可以用他们的大写形式来表示,如:\S表示不为空白字符的所有字符。因此,我们可以用[\s\S]、[\W\w]、[\D\d]来表示所有字符(突然想起sql注入的时候为了绕过等号采用<>号,原理大同小异)。有的时候还可以用’.’字符来匹配,然而点字符无法匹配换行符。

一个字符组匹配一个空位的字符,那么,当我们要匹配多个字符时,如果将字符组重复写多次,未免显得太笨拙繁琐。正则表达式为我们提供了一个量词符号{}。如\d{4}代表匹配数字4次,等价于\d\d\d\d。同样,{}符号可以写成范围形式,代表匹配左闭右闭区间的范围次数,如{5,6},则代表匹配5次或6次。有趣的是,这个区间可以单独缺少上区间或者下区间。如{5,}代表匹配不止5次,{,6}代表匹配最多6次,最少0次,但在有些语言下不适用,应该注意。

同样,量词也提供了简单写法,如+符号代表匹配不止1次,等同于{1,},*符号代表匹配大于等于0次,等同于{0,},?则代表匹配0次或1次,等同于{0,1}。

在严格匹配字符串的长度,以及要求一一相等时,应该采用^$符号,表示从字符串首匹配到尾。

之前提到匹配任意字符串时,可以采用’.’符号,然而点符号并不能匹配换行符\n,除非在单行匹配模式下。同时,点号时匹配优先词,采用的是贪婪模式匹配,所以在一些情况下可能会出现问题。

下一篇将探索贪婪模式与非贪婪模式匹配。

0%