资源说明:正则表达式
Regular Expression Tutorial
张子阳
jimmyzhang.cnblogs.com
jimmy_dev@163.com
目录
目录...................................................................................................................................................2
引言...................................................................................................................................................1
什么是正则表达式?.......................................................................................................................1
准备工作...........................................................................................................................................1
匹配单个字符...................................................................................................................................1
1.匹配固定单个字符...............................................................................................................1
2.匹配任意单个字符...............................................................................................................2
3.匹配“.”元字符.................................................................................................................3
4.匹配字符组...........................................................................................................................4
4.1 字符组的基本语法...................................................................................................4
4.2 在字符组中使用字符区间.......................................................................................5
4.3 反义字符组...............................................................................................................6
5.匹配特殊字符.......................................................................................................................7
5.1 匹配元字符...............................................................................................................7
5.2 匹配空字符...............................................................................................................8
5.3 匹配特定字符类型...................................................................................................9
5.3.1 匹配数字类型.................................................................................................9
5.3.2 匹配字母、数字、下划线.............................................................................9
5.3.3 匹配空字符...................................................................................................10
匹配多个字符.................................................................................................................................10
1.匹配一个或多个.................................................................................................................11
2.匹配零个或多个字符.........................................................................................................12
3.匹配零个或一个字符串.....................................................................................................13
4.匹配指定数目字符.............................................................................................................14
4.1 匹配固定数目的字符.............................................................................................14
4.2 匹配区间以内数目的字符.....................................................................................15
5.贪婪匹配和惰性匹配.........................................................................................................16
5.1 贪婪匹配、惰性匹配概述.....................................................................................16
5.2 贪婪匹配的匹配过程:.........................................................................................17
5.3 惰性匹配的匹配过程.............................................................................................17
5.4 值得注意的两个匹配模式.....................................................................................18
匹配边界.........................................................................................................................................19
1.匹配单词边界.....................................................................................................................19
2.边界及其相对性.................................................................................................................21
2.1 边界的定义.............................................................................................................21
2.2 边界的相对性.........................................................................................................22
3.匹配非单词边界.................................................................................................................23
3.匹配文本边界.....................................................................................................................24
3.1匹配文本首..............................................................................................................24
3.2匹配文本末..............................................................................................................25
匹配子模式.....................................................................................................................................26
1.子模式..................................................................................................................................26
2.“或”匹配.........................................................................................................................27
3.在子模式中使用“或”匹配.............................................................................................27
4.嵌套子模式.........................................................................................................................28
后向引用.........................................................................................................................................29
1.理解后向引用.....................................................................................................................29
2.后向引用的一个常见应用.................................................................................................32
3. .Net中的后向引用...........................................................................................................33
文本替换.........................................................................................................................................33
1.使用后向引用进行文本替换.............................................................................................33
1.1 高亮显示文本.........................................................................................................34
1.2 替换电话号码格式.................................................................................................34
2. .Net 中的文本替换.........................................................................................................35
预查和非获取匹配.........................................................................................................................35
1.理解非获取匹配.................................................................................................................35
2.正向预查.............................................................................................................................37
3.反向预查.............................................................................................................................39
4.正向、反向预查组合.........................................................................................................40
5.负正向预查、负反向预查.................................................................................................41
5.1 负正向预查.............................................................................................................41
5.2 负反向预查.............................................................................................................41
总结.................................................................................................................................................42
引言
正则表达式看上去并不像某种语言或者某个技术那么重要,仅靠它们你无法写出一个应用程序来。然而,它们却总是在你的开发过程中如影随形,不管是进行表单验证,还是高亮显示搜索结果,又或者是进行URL地址映射,总是需要使用它们。几乎所有的语言都对它进行了不同程度的支持,由此,足见其在文本匹配这一领域中的地位。
正则表达式应该算是开发人员应该掌握的一个轻量级的技能,然而,它稀奇古怪地匹配模式总让人们联想起外星语言。本文中,我期望能和大家一道,通过丰富地例子,由浅入深地对正则表达式作一个复习和回顾。
NOTE:本文章节的编排顺序和风格主要参考 Ben Forta 的《Sams Teach Yourself Regular Expressions in 10 Minutes》。
什么是正则表达式?
正则表达式也叫做匹配模式(Pattern),它由一组具有特定含义的字符串组成,通常用于匹配和替换文本。
通常情况下,如果一个文本中出现了多个匹配,正则表达式返回第一个匹配,如果将global设置为 true,则会返回全部匹配;匹配模式是大小写敏感的,如果设置了 ignore case 为true,则将忽略大小写区别。
本文中,有时会将 正则表达式 简称为 表达式、匹配模式 或者 模式,它们可以互换。 本文默认 global 和 ignore case 均为 true。
准备工作
在开始进行之前,我们首先需要一份工具来对表达式进行测试,在本文中,使用的是RegexTester 这个小程序,它的使用非常的简单明了,相信你随便摆弄下就会用了,这里就不对其使用再做说明了。
可以点这里下载:http://www.cnblogs.com/Files/JimmyZhang/RegexTester.zip
匹配单个字符
1.匹配固定单个字符
所有的 单个 大小写字母、数字,以及后面将要讲述的特殊字符,都是一个正则表达式,它们只能匹配单个字符,且这个字符与它本身相同,例如,对于表达式“i”:
Page 1 of 42
Text
Jimmy is a junior developer and jimmy lives in xi’an.
RegEx
i
Result
Jimmy is a junior developer and jimmy lives in xi’an.
需要注意:对于表达式“m”来说,它的匹配是jimmy,请注意这里的匹配方式:并不是一个“m”一次匹配了字符串“mm”,而是一个“m”分两次匹配了单个字符“m”,不管这两个“m”是 紧挨着 或者 如同上面的“i”那样分散在句子的不同地方。
将多个固定单个字符进行组合就构成了一个匹配固定字符串的表达式。例如:“Jimmy”,它也是一个正则表达式,它由多个匹配固定单个字符的表达式组成,它只可以匹配任何与它完全相同的文本:
Text
Jimmy is a junior developer and jimmy lives in xi’an.
RegEx
Jimmy
Result
Jimmy is a junior developer and jimmy lives in xi’an.
你可以将“Jimmy”这个表达式的匹配过程理解成这样:它由“j”、“i”、“m”、“m”、“y”这五固定的单个字符组成,对于每个单个字符来说,只能匹配与它完全相同的字符;而将这五个单个字符组合起来的时候,它就匹配 字符排列顺序与表达式完全相同 并且 相应位置上的字符也与对应字符相同 的字符串(实际上也就是与表达式完全相同的字符串)。
由于这种匹配方式的灵活度最小,只能匹配与它完全相同的字符,所以也叫“全字匹配”。
2.匹配任意单个字符
“.”可以匹配任意的 单个 字符、英文字母、数字,以及它本身。我们现在结合上面介绍的全字匹配来学习它:
Text
regular.doc regular1.exe regular2.dat expression.doc
Page 2 of 42
express.dat
RegEx
regular.
Result
regular.doc regular1.exe regular2.dat expression.doc express.dat
可以看到,对于表达式“regular.”来说,前面“regular”部分是一个全字匹配,只能固定的匹配“regular”字符串;后面的“.”部分,可以匹配任意单个字符(包含字符“.”本身)。
“.”可以连续使用,比如,我们可以写出“.e..”这样一个正则表达式。它将匹配所有:前面有任意一个字符,紧跟着一个e,随后又跟着任意两个字符的文本。
Text
regular.doc regular1.exe regular2.dat expression.doc express.dat
RegEx
.e..
Result
regular.doc regular1.exe regular2.dat expression.doc express.dat
NOTE:很多情况下,“.”不匹配换行。但在RegexTester这个工具中,它匹配换行,所以,这里有个值得注意的匹配,就是 回车符+exp,我在上面的代码中用绿色粗体标识出了(回车符难以标识)。
3.匹配“.”元字符
有的时候,我们不想让“.”去匹配任何的字符,仅仅想让它匹配“.”这一单个字符,也就是仅匹配它本身,此时,可以使用“\.”来对它进行转义。
Page 3 of 42
Text
regular.exe regular1.exe
RegEx
r\.
Result
regular.exe regular1.exe
表达式“r\.”仅仅匹配了字符串“r.”,没有匹配下面的 “r1”。
表达式“r.”则会匹配“r1”、“r.”、以及“re”。
NOTE:如果要匹配“\”,可以使用“\\”来对它进行转义。 后面还会介绍更多需要转义的字符。
4.匹配字符组
4.1 字符组的基本语法
“.”过于灵活了,它可以匹配几乎所有的单个字符。有的时候,我们只希望匹配有限个字符中的某一个。这个时候,可以使用字符组。
假设有这样一种情况,我们希望验证某个单词是不是拼写正确,比如说 “head” 是一个单词,“heat”也是一个单词,但“heay”就不是一个单词,所以,“hea”后面要么出现“d”,要么“t”,而如果我们使用“.”来进行匹配,那么不管是“heay”也好,“heas”也罢,都会被匹配(被认为是正确的单词)。
正则表达式提供 字符组 来解决这一问题,对于上例,“hea”后面仅可以匹配“d”或者“t”的情况,它的语法是 “[dt]”。中括号是特殊标记,用以划定属于组内的字符的界限,它所代表的含义是:“匹配d或者t”。
Text
bread heay teas head heat
RegEx
.ea[td]
Page 4 of 42
Result
bread heay teas head heat
NOTE:字符组虽然由多个字符构成,但它仍只匹配单个 字符,而字符组能够匹配的单个字符,即是它定义中的字符(“[]”内的字符)。“[]”本身不进行字符匹配,它仅仅划定字符组边界。
4.2 在字符组中使用字符区间
现在假设我们需要匹配一组文件名,它们的名称为 city0.jpg、city1.jpg...city9.jpg。根据前面介绍的内容,我们很容易写出这样的表达式:“city[0123456789].jpg”。没错!这样写法的确可以达到我们要的效果。如果说写10个阿拉伯数字你觉得并不困难,那么如果要匹配这样的文件名呢?a_1.jpg、b_1.jpg、c_1.jpg...z_1.jpg。这次,你的表达式变成这样了:“[abcdefghijklmnopqrstuvwxyz]_1\.jpg”,哇!看着就难受。
正则表达式提供了字符区间来简化这一写法,它的语法是:“起始字符-结束字符”。对于上面匹配阿拉伯数字的例子,它的写法是[0-9]。
NOTE:不一定非要将匹配写成“[0-9]”,完全可以根据需要写成“[0-3]”,它将仅匹配“0,1,2,3”这个区间。起始字符 和 结束字符,依据的是它的 ASCⅡ值的大小,即是说,将会匹配其ASCⅡ码位于 起始字符 和 结束字符 的ASCⅡ之间的所有字符(包含起始、结束字符)。另外,如果起始字符的ASCⅡ值大于结束字符的ASCⅡ值,例如,如果你写成“[3-0]”,则会出错,导致匹配失败。
Text
city.jpg city0.jpg city1.jpg city2.jpg city3.jpg city4.jpg
RegEx
city[1-3]\.jpg
Result
city.jpg city0.jpg city1.jpg city2.jpg
Page 5 of 42
city3.jpg city4.jpg
NOTE:如果要在字符组(“[”“]”内)中匹配“-”,需要使用转义符,写法是“\-”; 而在“[”“]”以外,“-”变成了一个普通字符,无需再进行转义。
同样的道理,我们可以写出“[a-z]”来匹配所有的小写字母,“[A-Z]”匹配所有的大写字母,这里就不再举例子了。
现在假设需要在HTML中匹配所有的RGB颜色,我们知道,在Web中,颜色通常表示为诸如“#FF00CC”这样的值,那么结合上面讲述的内容,我们可以像这样使用匹配:
Text
RegEx
#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]
Result
NOTE:之前说了,我们默认Ignore Case是为True的,也就是说忽略大小写。因此,本例中的表达式也可以写作:“#[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]”
4.3 反义字符组
有的时候,我们需要匹配“除了某些字符以外”的其他字符,这时候,我们可以使用反义字符组,其语法是:“[^字符集合]”
我们在以上面的例子为例,现在我们匹配“city1.jpg、city2.jpg、city3.jpg”以外的文件名。
Text
city.jpg city0.jpg city1.jpg city2.jpg city3.jpg city4.jpg citys.jpg cityss.jpg
RegEx
city[^1-3]\.jpg
Page 6 of 42
Result
city.jpg city0.jpg city1.jpg city2.jpg city3.jpg city4.jpg citys.jpg cityss.jpg
注意:这里并没有匹配“city.jpg”。因为,不管是 普通字符组 还是 反义字符组,它总是 确定一定以及肯定 要匹配一个字符的。换言之,在本例的模式中,“city”和“.”之间是无论如何需要有一个字符的,而“city.jpg”之间没有,所以它不符合此模式。
5.匹配特殊字符
5.1 匹配元字符
我们先对元字符作一个定义:元字符是在正则表达式中具有特殊含义的字符。如果我们之前已经介绍过的,“.”就是一个元字符,它用来匹配任意单个字符。当我们要匹配字符“.”本身的时候,需要使用“\”来对它进行转义:“\.”
很容易就看出“\”也是一个元字符,它叫做转义符。所以,当我们需要匹配字符“\”的时候,就需要对它进行转义:“\\”。
回想一下之前讲述的字符组,我们知道“[”和“]”也是元字符,当我们需要匹配“[”和“]”字符的时候,需要分别写作:“\[”和“\]”。
举个例子,加入我们需要匹配 “City[0].Name”,却写成了下面这样:
Text
City[0].Name = "Xian"; City[0]_Name = "Shanghai"; City0.Name = "Hangzhou"; City0_Name = "Beijing";
RegEx
City[0].Name
Result
City[0].Name = "Xian"; City[0]_Name = "Shanghai";
Page 7 of 42
City0.Name = "Hangzhou"; City0_Name = "Beijing";
因为没有对“[”、“]”和“.”进行转义,所以“[0]”被当作字符组来解释,因为字符组中只有一个字符“0”,所以,它仅能匹配一个“0”,所以“City[0]”相当于“City0”。又因为没有对“.”进行转义,所以它可以匹配 它本身 以及 “_”。
正确的写法:City\[0\]\.Name
Text
City[0].Name = "Xian"; City[0]_Name = "Shanghai"; City0.Name = "Hangzhou"; City0_Name = "Beijing";
RegEx
City\[0\]\.Name
Result
City[0].Name = "Xian"; City[0]_Name = "Shanghai"; City0.Name = "Hangzhou"; City0_Name = "Beijing";
5.2 匹配空字符
我想先介绍一下回车换行的由来。通常,当我们在键盘上敲击一下回车键时,不管光标此时在哪里,总是会新起一行,然后将光标位于新行的首位置。这在计算机上看起来一气呵成,用一个符号来表示就OK了,可在正则表达式中,以及很多语言中(比如VBScript),却被表示成了两个动作,一个叫“回车”(Carriage Return),一个叫“换行”(Line Feed),在语言,比如VBScript中,就表示成了:Chr(13)&Chr(10)。这与打印机的工作原理有关,大家知道,打印机先于计算机键盘很多年,是键盘的雏形,在打印机上换行时,将进行两个动作:1、将打印头换到下一行;2、将打印头返回到新行的行首位置。也就分别对应了现在的“换行”和“回车”。
在正则表达式中,比较常用的三类空白字符如下表所示:
元字符
匹配描述
\r
回车
\n
换行
\t
Tab 键
这种情况使得书写表达式时,变得稍有不便,例如,如果我们想匹配一个换行的效果,我们需要将表达式写成“\r\n”。然后,我们在IE和Firefox中用javascript分别做个测试,却地发现对于IE6(NOTE:IE7我没有试过)来说“\r\n”可以匹配一个换行,而在Firefox中,只用
Page 8 of 42
一个“\n”就可以了,使用“\r\n”则无法匹配。
对于我们的测试工具RegexTester 来说,它也是只使用“\n”来匹配一个换行的效果。
NOTE:不常用的有:\f,换页;\v,垂直Tab。
5.3 匹配特定字符类型
结合“匹配元字符”和“匹配空字符”这两个小节,我们发现这样一个规律:
本源码包内暂不包含可直接显示的源代码文件,请下载源码包。