精通正则表达式
原文http://blog.csdn.net/wlzhengzebiaodashi/article/details/2213225
在正则表达式中,元字符(Metacharacter)是一类非常特殊的字符,它能够匹配一个位置或字符集合中的一个字符,如.、/w等。根据功能,元字符可以分为两种类型:匹配位置的元字符和匹配字符的元字符。 匹配位置的元字符包括3个字符:^、$和/b。其中,^(脱字符号,通常在文章中插入字时使用)和$(美元符号)都匹配一个位置,它们分别匹配行的开始和结尾。以下正则表达式匹配以“String”开头的行,即被匹配的行的第一个字符串为“String”。 ^String (1) 以下正则表达式匹配以“String”结尾的行,即被匹配的行的最后一个字符串为“String”。 String$ (2) 以下正则表达式匹配以“String”开始和结尾的行,即被匹配的行的第一个字符串和最后一个字符串都为“String”。实际上,该行只包含字符串“String”。 ^String$ (3) 以下正则表达式匹配一个空行,该行中不包含任何字符串。 ^$ (4) 以下正则表达式匹配任意行。该表达式只匹配行中的开始位置,因为任意行都包括其开始位置,所以该表达式将匹配任意行。 ^ (5) 元字符/b和^、$具有相似性,它也是匹配一个位置。/b可以匹配单词的开始或结尾,即单词的分界处。通常情况下,英文单词往往由空格符号或标点符号或换行符号来分隔,但是元字符/b不匹配空格符号、标点符号和换行符号中的任何一个,它仅仅匹配一个位置。以下正则表达式匹配以“Str”开头的字符串,如“String”、“String Format”等。 /bStr (6) 正则表达式/bStr匹配的字符串必须“Str”开头,且“Str”之前是单词的分界处。正则表达式/bStr不能描述或限定“Str”之后的字符串的形式。以下正则表达式匹配以“ing”结尾的字符串,如“String”、“This is a String”等。 ing/b (7) 正则表达式ing/b匹配的字符串必须“ing”结尾,且“ing”之后是单词的分界处。以下正则表达式匹配一个完整的单词“String”。 /bString/b (8) 注意:在某些特定环境或语言下,还可以分别采用/<和/>来匹配单词的开始和结束位置。它们在效果上和元字符/b等效,即都匹配单词的边界这两个位置(开始位置和结束位置)。 匹配字符的元字符包括7个字符:.(点号)、/w、/W、/s、/S、/d和/D。其中,.(点号)匹配除换行符号之外的任意字符;/w匹配单词字符(包括字母、数字、下划线和汉字);/W匹配任意的非单词字符;/s匹配任意的空白字符,如空格、制表符、换行符、中文全角空格等;/S匹配任意的非空白字符;/d匹配任意的数字;/D匹配任意的非数字字符。以下正则表达式匹配一个非空行,该行中可以包含除换行符号之外的任意字符。 ^.$ (9) 以下正则表达式匹配一个非空行,且该行中只能包含字母、数字、下划线和汉字中的任意字符。 ^/w$ (10) 以下正则表达式匹配以字母“a”开头的长度等于8的任意单词。 /ba/w/w/w/w/w/w/w/b (11) 正则表达式/ba/w/w/w/w/w/w/w/b匹配单词“anterior”的方式如图所示。 以下正则表达式匹配以字母“a”开头的、后跟随形如“3个字符”+“3个字符”+“1个非数字字符”的、长度等于8的任意单词。 /ba/w/w/w/d/d/d/D/b (12) 正则表达式/ba/w/w/w/d/d/d/D/b匹配单词“ante123_”的方式如图2.2所示。
在正则表达式中,元字符通常一次只能匹配一个位置或字符集合中的一个字符。通常情况下,如果要匹配数字、字母、空白等字符时,可以直接使用与这些集合相对应的元字符。然而,如果要匹配的字符集合(如集合[0,1,2,3,4,5])没有与之相对应的元字符时,则需要自定义匹配的字符集合。此时,可以使用字符类解决这个一个问题。字符类是一个字符集合,如果该字符集合中的任何一个字符被匹配,则它就会找到该匹配项。 字符类是正则表达式中的“迷你”语言,可以在方括号“[]”中定义。最简单的字符类是方括号“[]”和一个字母表表构成,如元音字符类[aeiou]。以下正则表达式匹配数字0、1、2、3、4、5、6中的任何一个。 [0123456] (20) 以下正则表达式可以匹配任何数字(即0、1、2、3、4、5、6、7、8、9)。 [0123456789] (21) 以下正则表达式匹配HTML标记中的“<H1>”、“<H2>”、“<H3>”、“<H4>”、“<H5>”或“<H6>”。 <H[123456]> (22) 以下正则表达式匹配字符串“Jack”或者“jack”。 [Jj]ack (23) 然而,正则表达式[0123456789]的书写非常不方便。因此,正则表达式引入了连接符“-”定义字符的范围。以下正则表达式等价于正则表达式[0123456789]。 [0-9] (24) 以下正则表达式可以匹配任何小写字母。 [a-z] (25) 以下正则表达式可以匹配任何大写字母。 [A-Z] (26) 注意:当且仅当在字符类中的连接符“-”不是第一个字符时,它才具有特殊的含义:它可以指定字符类的最大边界和最小边界之间的任何字符。它的具体含义由具体的字符类决定。因此,字符类的最大边界和最小边界,以及字符在ASCII或Unicode表中出现的顺序共同确定了连接符“-”指定的字符的范围。 如果要在字符类中包括连接符“-”,则必须将它作为第一个字符。如正则表达式[-a]匹配字符“-”或者“a”。 在字符类中,若字符“^”是字符类的第一个字符,则表示否定该字符类,即匹配除了该字符类之外的任意字符。以下正则表达式可以匹配任何非元音字符。 [^aAeEiIoOuU] (27) 以下正则表达式可以匹配除连接符“-”之外的任何字符。 [^-] (28) 以下正则表达式匹配字符a之后不是字符串b的字符串。 a[^b] (29) 使用工具Regex Tester测试正则表达式(29),结果如图所示。 注意:正则表达式中的元字符在字符类中不做任何特殊处理,它仅仅表示一个自身的字符。如正则表达式[-.]只能匹配字符“-”和“.”,它不能匹配除字符“-”和“.”之外的字符。因此,在字符类中使用元字符时,不需要使用转义操作。 在正则表达式中,常用的字符类如表2-2所示。 表2-2 常用的字符类
注意:在表2-2中,表达式/p{name}和/P{name}为.NET Framework所支持。 正则表达式的元字符一次一般只能匹配一个位置或一个字符,如果要匹配零个或一个或多个字符时,则需要使用限定符。限定符用于指定允许特定字符或字符集自身重复出现的次数。如{n}表示重复n次、{n,}表示重复至少n次、{n,m}表示重复至少n次,最多m次。常用限定符的说明如表2-5所示。 表2-5 常用限定符
以下正则表达式可以匹配字符串“color”或者“colour”。表达式u?表示字母“u”可以出现1次或者不出现。 colou?r (36) 以下正则表达式可以匹配字符串“four”或者“for”。表达式u?表示字母“u”可以出现1次或者不出现。 fou?r (37) 以下正则表达式匹配以字符串“name”开头的、以数字字符串结尾的字符串。其中,表达式/d+可以匹配长度至少为1的数字字符串。 /bname/d+/b (38) 以下正则表达式匹配被尖括号括起来的、以字符串“asp:TextBox ”(最后一个字符是空格)开头的字符串。正则表达式<asp:TextBox [^>]+>中的字符类[^>]匹配除了尖括号“>”之外的任何字符。 <asp:TextBox [^>]+> (39) 以下正则表达式匹配以字母a开头的单词。/w匹配一个单词字符,/w*表示该单词字符可以重复零次或多次。 /ba/w*/b (40) 正则表达式/ba/w*/b匹配单词“anterior”的过程如图2.10所示,匹配的具体步骤如下: (1)匹配单词的开始位置; (2)在步骤①时匹配字符a; (3)匹配字符a之后,该表达式可以直接通过步骤②匹配到单词的结束位置,并完成整个匹配过程,从而匹配单词“a”; (4)该表达式在匹配字符a之后,可以通过步骤③来匹配任何单词字符; (5)重复步骤④一次或多次,即匹配一个或多个任何单词字符; (6)匹配到单词的结束位置,并完成整个匹配过程,从而匹配到以字符a开头的长度大于1的单词。
限定符除了使用*、+、?之外,还可以使用数字直接指定重复的次数。{n}表示重复n次;{n,}表示至少重复n次,而最多重复的次数不限制;{n,m}(其中,n<=m)表示至少重复n次、最多重复m次。以下正则表达式匹配3位的整数,该正则表达式和正则表达式/d/d/d等价。 /d{3} (41) 以下正则表达式匹配3位以上(包括3位)的整数,该正则表达式和正则表达式/d/d/d/d*或/d/d/d+等价。 /d{3,} (42) 以下正则表达式匹配3位或4位的整数,该正则表达式和正则表达式/d/d/d/d?等价。 /d{3,4} (43) 以下正则表达式匹配当前国内的手机号码:即以字符串“13”开头的、后接连续9个数字的字符串。 13/d{9} (44) 以下正则表达式匹配当前国内部分地区的固定电话号码。其中,号码的前3位为区号,后8位为本地号码,区号和本地号码使用连接符号“-”进行连接。 0/d{2}-/d{8} (45) 以下正则表达式匹配当前国内部分地区的固定电话号码。其中,号码的前4位为区号,后7位为本地号码,区号和本地号码使用连接符号“-”进行连接。 0/d{3}-/d{7}
如果在限定符*、+、?、{n}、{n,}和{n,m}之后再添加一个字符“?”,则表示尽可能少的重复字符“?”之前的限定符号的重复次数,这种方式匹配被称为懒惰匹配。与之相对应的是贪婪匹配,即仅仅使用单个限定符*、+、?、{n}、{n,m}的匹配。常用的懒惰限定符如表2-6所示。 表2-6 常用懒惰限定符
以下正则表达式匹配以字母a开头的、以字母b结束的、最长的字符串。此时,这是一种贪婪匹配。 a.*b (48) 以下正则表达式匹配以字母a开头的、以字母b结束的、最短的字符串。此时,这是一种懒惰匹配。 a.*?b (49) 如果将正则表达式a.*b应用于字符串“aabab”,则匹配字符串“aabab”。如果将正则表达式a.*?b应用于字符串“aabab”,则匹配字符串“aab”和字符串“ab”,而不会匹配字符串“aabab”。 使用工具Regex Tester分别测试正则表达式(48)和(49),结果分别如图2.12和2.13所示。 以下正则表达式匹配以字母a开头的、以字母b结束的、长度为2或者3的字符串。此时,这是一种贪婪匹配。 a.?b (52) 以下正则表达式匹配以字母a开头的、以字母b结束的、长度为3的字符串。此时,这是一种懒惰匹配。 a.??b (53) 正则表达式a.??b在匹配过程中,字母a和字母b之间的字符要么出现,要么最多出现1次。使用工具Regex Tester分别测试正则表达式(52)和(53),结果分别如图(52)和(53)所示。
以下正则表达式匹配以字母a开头的、以字母b结束的、长度至少为3的字符串。此时,这是一种贪婪匹配。 a.{1,}b (54) 以下正则表达式匹配以字母a开头的、以字母b结束的、长度至少为3的字符串。此时,这是一种懒惰匹配。 a.{1,}?b (55) 正则表达式a.{1,}?b在匹配过程中,字母a和字母b之间的字符串实际上只重复了1次。如果将正则表达式a.{1,}b应用于字符串“avbab”,则匹配字符串“avbab”。如果将正则表达式a.{1,}?b应用于字符串“avbab”,则匹配字符串“avb”,而不会匹配字符串“avbab”。使用工具Regex Tester分别测试正则表达式(54)和(55),结果分别如图2.18和2.19所示。 正则表达式0/d{2}-/d{8}和0/d{3}-/d{7}分别匹配区号为3位和4位的固定电话号码,如果需要同时匹配区号为3位和4位的固定电话号码时,使用替换可以满足这一个需求。最简单的替换使用字符“|”表示,它表示如果某一个字符串匹配了正则表达式中的字符“|”的左边或者右边的规则,那么该字符串也匹配了该正则表达式。 以下正则表达式匹配了当前国内部分地区的两种固定电话号码:一种是号码的前4位为区号,后7位为本地号码;另一种是号码的前3位为区号,后8位为本地号码。其中,区号和本地号码都使用连接符号“-”进行连接。 0/d{2}-/d{8}|0/d{3}-/d{7} (56) 以下正则表达式匹配了当前国内部分地区的3种固定电话号码:一种是号码的前4位为区号,后7位为本地号码;另一种是号码的前3位为区号,后8位为本地号码;最后一种是号码的前4位为区号,后8位为本地号码。其中,区号和本地号码都使用连接符号“-”进行连接。 0/d{2}-/d{8}|0/d{3}-/d{7}|0/d{3}-/d{8} (57) 以下正则表达式匹配当前国内部分地区的区号为4位的固定电话号码。其中,区号和本地号码可以使用连接符号“-”进行连接,也可以不使用连接“-”符号。 0/d{3}-/d{7}|0/d{3}[-]?/d{7} (58) 使用工具Regex Tester测试正则表达式(58),测试结果如图所示。其中,电话号码0731-1234567和07311234567都均被匹配。 正则表达式[Jj]ack可以匹配字符串“Jack”或者“jack”。该正则表达式还可以使用替换来实现同样的匹配效果。如下正则表达式等效于正则表达式[Jj]ack。 Jack|jack (59) 如下正则表达式等效于正则表达式Jack|jack。因此,正则表达式[Jj]ack、Jack|jack和Jack|jack能够匹配的所有字符串是相同。 (J|j)ack (60) 使用工具Regex Tester分别测试正则表达式[Jj]ack和(60),结果分别如图2.21和2.22所示。从图中可以看到,两个正则表达式匹配的结果是相同的。 正则表达式的常用替换说明如表2-7所示。 表2-7 常用替换
注意:字符|在匹配表达式时,它首先匹配|字符的左侧部分。当左侧部分不匹配时,它才尝试匹配|字符的右侧部分。 给定以下两个正则表达式 /d{5}-/d{3}|/d{5} (61) /d{5}|/d{5}-/d{3}
(62) 根据字符|的匹配原则(优先匹配左侧表达式),正则表达式/d{5}|/d{5}-/d{3}只会匹配5位的数字字符串,而不会匹配用连接符合连接的8位数字字符串。然而,正则表达式/d{5}-/d{3}|/d{5}能够匹配用连接符合连接的8位数字字符串或者5位的数字字符串。因为,该表达式首先尝试匹配用连接符合连接的8位数字字符串,只有当未匹配时,才匹配5位的数字字符串。 使用工具Regex Tester分别测试了正则表达式(61)和(62),测试结果分别如图2.23和2.24所示。正则表达式/d{5}|/d{5}-/d{3}只匹配了字符串“12345”。而正则表达式/d{5}-/d{3}|/d{5}可以匹配字符串“12345-678”和字符串“12345”。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |