学习正则表达式

作者:ET Dreams http://blog.csdn.net/etmonitor/
Regular Expressions (1) ---- What is Regular Expressions?

 

正则表达式是常见常忘,所以还是记下来比较保险,于是就有了这篇笔记。

希望对大家会有所帮助。J

1.什么是正则表达式.............................................................................................................................................................. 2

2.正则表达式的起源............................................................................................................................................................. 2

3. 正则表达式使用祥解........................................................................................................................................................ 3

3.1基本语法.............................................................................................................................................................................. 3

3.1.1普通字符..................................................................................................................................................................... 3

3.1.2非打印字符................................................................................................................................................................. 3

3.1.3特殊字符..................................................................................................................................................................... 3

3.1.4字符集........................................................................................................................................................................... 4

3.1.5在字符集中使用元字符............................................................................................................................................. 5

3.1.6预定义字符集.............................................................................................................................................................. 5

3.1.7 限定符........................................................................................................................................................................... 6

3.1.8定位符........................................................................................................................................................................... 6

3.1.9 “.”元字符...................................................................................................................................................................... 7

3.1.10用 “|”表示选择.......................................................................................................................................................... 8

3.1.11用 “()”表示分组.................................................................................................................................................. 8

3.1.12 “?”的补充说明.......................................................................................................................................................... 8

3.1.13给正则表达式添加注释......................................................................................................................................... 8

3.1.14操作符的运算优先级............................................................................................................................................... 8

3.2 高级话题............................................................................................................................................................................... 9

3.2.1反向引用..................................................................................................................................................................... 9

3.2.2在正则表达式中指定模式option........................................................................................................................... 9

3.2.3 Lookaround断言..................................................................................................................................................... 10

4. 正则表达式基本语法索引............................................................................................................................................ 11

5.   正则表达式高级语法索引.............................................................................................................................................. 15

6.   参考资料................................................................................................................................................................................. 17

7.   推荐工具................................................................................................................................................................................. 17

 

 

 

 

 

 

 

 

 

 

 

 

 

1.什么是正则表达式

 

简单的说,正则表达式是一种可以用于文字模式匹配和替换的强有力的工具。是由一系列普通字符和特殊字符组成的能明确描述文本字符串的文字匹配模式。

正则表达式并非一门专用语言,但也可以看作是一种语言,它可以让用户通过使用一系列普通字符和特殊字符构建能明确描述文本字符串的匹配模式。除了简单描述这些模式之外,正则表达式解释引擎通常可用于遍历匹配,并使用模式作为分隔符来将字符串解析为子字符串,或以智能方式替换文本或重新设置文本格式。正则表达式为解决与文本处理有关的许多常见任务提供了有效而简捷的方式。

正则表达式具有两种标准:

  • 基本的正则表达式(BRE – Basic Regular Expressions)
  • 扩展的正则表达式(ERE – Extended Regular Expressions)。

ERE包括BRE功能和另外其它的概念。

 

正则表达式目前有两种解释引擎:

  • 基于字符驱动(text-directed engine)
  • 基于正则表达式驱动(regex-directed engine)

Jeffery Friedl把它们称作DFA和NFA解释引擎。

 

约定:

为了描述起来方便,在本文中做一些约定:

  1. 本文所举例的所有表达时都是基于NFA解释引擎的。
  2. 正则表达式,也就是匹配模式,会简写为Regex。
  3. Regex的匹配目标,也就是目标字符串,会简写为String。
  4. 匹配结果用会用黄色底色标识。
  5. 用1/+1=2 括起来的表示这是一个regex。
  6. 举例会用以下格式:

Regex

Target String

Description

test

This is a test

会匹配test,testcase等

 

2.正则表达式的起源

正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。

1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。

随后,发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的qed 编辑器。从那时起直至现在正则表达式都是基于文本的编辑器和搜索工具中的一个重要部分。具有完整语法的正则表达式使用在字符的格式匹配方面上,后来被应用到熔融信息技术领域。自从那时起,正则表达式经过几个时期的发展,现在的标准已经被ISO(国际标准组织)批准和被Open Group组织认定。

3. 正则表达式使用祥解

最简单的正则表达式相信大家都已熟悉并且经常使用,那就是文字字符串。特定的字符串可通过文字本身加以描述;像 test这样的Regex模式可精确匹配输入的字符串”test”,但是它也可以匹配this is a testcase,这就不是我们想要得结果。

当然,使用正则表达式匹配等于它自身的精确字符串是没有价值的实现,不能体现正则表达式的真正作用。但是,假如要查找的不是test,而是所有以字母 t 开头的单词,或所有4个字母的单词,那该怎么办?这超出了文字字符串的合理范围。所以我们才需要深入地研究正则表达式。

3.1基本语法

虽然正则表达式并非一门专用语言,但它也有一些特殊的规定,也可以称之为基本语法。

正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。

构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。

可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。

3.1.1普通字符

由所有那些未显式指定为元字符的打印和非打印字符组成。这包括所有的大写和小写字母字符,所有数字,所有标点符号以及一些符号。

3.1.2非打印字符

非打印字符也是普通字符,单独列出来便于参考。

Symbol

Description

/cx

匹配由x指明的控制字符。例如, /cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。

/f

匹配一个换页符。等价于 /x0c 和 /cL。

/n

匹配一个换行符。等价于 /x0a 和 /cJ。

/r

匹配一个回车符。等价于 /x0d 和 /cM。

/s

匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ /f/n/r/t/v]。

/S

匹配任何非空白字符。等价于 [^ /f/n/r/t/v]。

/t

匹配一个制表符。等价于 /x09 和 /cI。

/v

匹配一个垂直制表符。等价于 /x0b 和 /cK。

 

Regex中可以使用非打印字符。/t会匹配一个tab字符(ASC||),/r 会匹配一个回车(0x0D),/n 会匹配一个换行符(0x0A)。应该注意的是:Windows使用/r/n表示一行的结束,而UNIX使用/n 。

同样,我们可以在Regex中使用16进制的ASCⅡ码或者ANSI标准码。在拉丁语中,版权符号的代码是0xA9,所以我们也可以这样来匹配版权符号 /xA9 。另外一个匹配tab的写法是:/x09 。但是注意,第一位的“0”必须去掉。

 

3.1.3特殊字符

特殊字符也叫做元字符,保留字符(Metacharactor),在Regex中表示特殊的意义,大部分的意思在不同的上下文中的意义是不同的,这里只列出最普遍的意义。

特殊字符共有11个:

Symbol

Description

$

匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 '/n' 或 '/r'。要匹配 $ 字符本身,请使用 /$。

( )

标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 /( 和 /)。

*

匹配前面的子表达式零次或多次。要匹配 * 字符,请使用 /*。

+

匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 /+。

.

匹配除换行符 /n之外的任何单字符。要匹配 .,请使用 /。

[

标记一个中括号表达式的开始。要匹配 [,请使用 /[。

?

匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 /?。

/

将下一个字符标记为或特殊字符、或原义字符、或反向引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'/n' 匹配换行符。序列 '//' 匹配 "/",而 '/(' 则匹配 "("。

^

匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 /^。

{

标记限定符表达式的开始。要匹配 {,请使用 /{。

|

指明两项之间的一个选择。要匹配 |,请使用 /|。

 

在元字符前加 / 转义符,可以把特殊字符当作普通字符来使用。

比如:如要要匹配 1+1=2 ,正确的正则表达式应该为1/+1=2。否则, + 会被当作特殊字符对待。

除了特殊字符,所有的其他字符都不应该加 / 。因为 / 也是一个特殊字符。/ 和普通字符组合在一起也可以创造一种特殊的意义。比如 /d 表示匹配所有的数字。

作为程序员,单引号和双引号不是特殊字符会也许让我们感到很惊讶。但这是正确的。因为我们在编程的时候,编程语言会知道引号之间的哪些字符表示特殊意义,编译器在把字符串x传递给regex解释引擎之前,会把它们处理成regex。比如,在C#中,如果我们要匹配  1/+1=2 ,在程序中我们要这样写: “1//+1=2” ,C#编译器会把 “//” ,处理为一个“/”  。同样,如果要匹配 C:/Temp ,首先,正则表达式要这样写 C://Temp,然后在程序中我们应该这样写:“ C:////temp”。

3.1.4字符集

            字符集描述了一组字符,Regex解释器会认为匹配字符集中的一个字符就可以认为匹配成功。

字符集用[ ]括起来即可。

            比如gr[ae]y就可以匹配gray或者grey。

            字符集只能匹配一个字符,gr[ae]y就不能和graey匹配。字符集中的字符顺序是任意的,得到的结果都是唯一的。

            可以在字符集中用连字符“-”来表示一个范围。[0-9]的结果和[0123456789]的匹配结果都是相同的。字符集中的范围可以有多种。比如[0-9a-fA-F]表示匹配所有的16进制,包括大小写。也可以把范围和单个字符组合在一起用,[0-9a-fxA-FX]表示匹配所有的16进制或者一个字符X。字符集的顺序不会影响结果。

            在字符集的开始标志“[”后面加上一个“^”符号,表示否定,表示匹配除字符集中定义的字符以外的所有字符。包括非打印字符和行结束符。

            注意:字符集匹配的一个字符,而不是一个位置。所以。q[^u]的意义不是“q后面的字符不是u”。而是“q后面的字符可以是除了u以外的所有字符”。

            q[^u]不会和Iraq匹配。

但是会和Iraq is a country匹配,因为q后面的空格字符是一个“不是u的字符”。

3.1.5在字符集中使用元字符

字符集中的元字符只能是 ‘]’, ‘/’, ‘^’, 和 ‘-‘ 。

其他元字符在字符集中都失去了特殊意义,表示的只是一个普通字符。也不需要用加“/”。

比如:

匹配一个“*”或者“+”,用[*+]就足够了。即使给他们加上“/”,regex解释器也会把他们忽略掉。

 

四种特殊字符的处理:

在字符集中要表示“]”,“^”和“-”需要在后面加上转义符“/”,来表示它们代表的分别是普通字符“]”,“^”和“-”。

也可以把它们放在一个不能表示特殊意义的位置,后一个方法比较好,因为他们不会影响可读性。

  • “^”

要想匹配一个“^”,可以把它放在除了紧跟“[”的任意一个位置。

Regex

String

Description

[x^]

A string with x and ^.

匹配x或者“^”

 

  •  “]”

可以把“]”放在紧跟着“[”的位置,或者使用否定字符集。

Regex

String

Description

[]x]

A string with x and ]

匹配x或者“]”

[^]x]

A string with x and ]

匹配除了x和”] ”以外的所有字符

  •  “/”

要想把“/”当作一个普通字符来匹配,而不是一个特殊字符,必须把“/”再用一个“/”括起来。

Regex

String

Description

[//x]

A string with x and /

匹配x或者“/”

 

  •  “-”

连字符可以放在紧跟着“[”的后面,或者正好“]”的前面,或者紧跟着“^”的后面。

Regex

String

Description

[-x]

A string with x and -

匹配x或者“-”

[x-]

A string with x and -

匹配x或者“-”

3.1.6预定义字符集

因为很多字符集是经常使用的,所以Regex解释器预定义了一些常用字符集:

Regex

Meaning

Description

/d

[0-9]

所有数字

/w

[a-zA-Z]

表示所有的字符,和文化字体有关

/s

[ /t/r/n]

空格,回车和tab。和文化字体有关

 

预订一字符集可以既可以用在字符集里面,也可以用在字符集外面。

Regex

String

Description

/s/d

1<space>+<space>2<space>=<space>3

匹配后面紧跟着一个数字的空白符

[/s/d]

1<space>+<space>2<space>=<space>3

匹配一个单独的字符或者一个数字或者一个空白符

[/da-fA-F]和[0-9a-fA-F]的匹配结果是一样的。

 

同样,在预定义字符集前面加一个“^”符号表示否定。它们也有预先定义好的表示:

Regex

Meaning

Description

/D

[^/d]

非数字

/W

[^/w]

非字符,和文化字体有关

/S

[^/s]

非空格,回车和tab。和文化字体有关

 

在“[]”使用否定预订一字符集时要特别心。[/D/S]不等于[/^d/s]。[/^d/s]会匹配除了数字和空白符以外的所有字符。而[/D/S]会匹配要么不是一个数字,要么是空白符。因为数字不是空白符,空白符也不是数字,所以[/D/S]会匹配任意的字符。

3.1.7 限定符

限定符提供了一种简单方法,用于指定在模式中允许特定字符或字符集自身重复出现的次数。限定符始终引用限定符前(左边)的模式,通常是单个字符,除非使用括号创建模式组。

限定符有*或+或?或{n}或{n,}或{n,m}共6种。

Symbol

Description

Description

?

0次获1次

 

*

0次或n次

 

+

1次或n次

 

{min, max}

最少min次,最多max次

Max必须大于等于min。

{min,<不指定> }

最少min次,或者n次

 

{min}

精确的重复min次

 

在字符集后面使用 “?”,”*”,”+”,表示重复。会重复整个的字符集,而不是重复匹配的那个字符。

Regex

String

意义

[0-9]+

846111

匹配数字

([0-9))+

846,111

匹配数字相同的数字

[0-9]+会匹配846,也会匹配111。

如果想要重复的只是匹配的那个字符,而不是整个字符集,则必须使用反向引用

([0-9])/1+ 只会匹配111,而不会匹配846。

(第二部分高级话题会讲道)

如果目标string是 811116。则1111会被匹配。如果不想这样,则需要使用

lookahead和lookbehind。

(第二部分高级话题会讲道)

3.1.8定位符

到现在为止,我们已经熟悉了普通字符、特殊字符(元字符)和字符集。在这两种情况下,Regex匹配的都是一个字符。

定位符是另外一种,它不匹配字符,相反,它匹配的是一个位置。

定位符有几种:

Regex

Function

Description

^

第一个字符之前的位置

包含换行符

$

最后一个字符后面的位置

包含换行符

/A

总是匹配string的第一个位置

不包含换行符

/Z

总是匹配string的最后一个位置

不包含换行符

 

Regex

String

意义

^

Abc

匹配A之前的位置

$

Abc

匹配c后面的位置

^A

Abc

匹配A

^b

Abc

不能匹配

c$

Abc

匹配c

A$

Abc

不能匹配

 

词的边界

还有一种定位符匹配的是一个词(word)的边界。用/b表示。

词(word)是由可以组成词的字符组成(“word characters”),“word characters”就是可以组成词的字符,不包括非打印字符和回车换行。

有四种不同的位置被认为是词的边界:

  1. 第一个字符之前的位置,如果第一个字符是一个“word character”。
  2. 最后一个字符之后的位置,如果最后一个字符是一个“word character”。
  3. 介于词和非词之间的紧跟着词的位置。
  4. 介于非词和词之间的紧跟着非词的位置

所有的word characters都可以用/w来表示。

所有的non-word characters都可以用/W来表示。

 

/b匹配一个词的边界。

/B表示一个非词的边界的位置,它能匹配任意一个不是次的边界的位置。

3.1.9 “.”元字符

在正则表达式中,“.”是用的最多的一个元字符,同时,它也是最容易用错的一个。所以我们单独来讲。

“.”几乎匹配任何字符。唯一的一个例外是换行符。

这个例外存在是有历史原因的。第一个用正则表达式的工具是基于换行符的。它从文件中读取一行字符,然后用去匹配。因为在这些工具中,string中永远不可能有换行符,所以“.”也永远不会和换行符匹配。

现代的工具可以用正则表达式去和很大的一个string甚至整个文件去匹配。所以现在的Regex解释器都含有一个选项,激活以后就可以让“.”去匹配所有的字符,包括换行符。

 “.”是一个非常强大的元字符。它可以让我们偷懒。但是我们要慎重的使用。我们看一个例子:

我们要匹配一个mm/dd/yy的格式的日期。但是我们可以让用户指定日期的分割符。一个简单的Regex是:/d/d./d/d./d/d这个看起来可以实现。它会很好的匹配04/09/07。问题是: 04409407也会被匹配。因为第三个4和第五个4都会被“.”匹配。这不是我们想要得结果。

/d/d[-/.]/d/d[-/.]/d/d是一个比上面的好的一个方法,用户可以指定“-”,“.”,“/”作为日期的分割符。因为“.”在字符集中不表示一个特殊字符,所以我们不需要在“.”之前加”/”。

但这个方法还不完美,它会匹配 99/99/99 , [0-1]/d[-/.][0-3]/d[-/.]/d/d也许会好一些。虽然它仍旧会匹配19/39/99, 。方法够用就好了,不必追求完美,如果这个是用来验证用户需求,可能还需要改进,如果只是用来分析一段code,或许已经足够了。

如果我们要匹配一段带双引号的字符串。听起来很容易,我们可以在两个双引号之间放任意多个任意字符。Regex可能会这么写:“.*”,这个会匹配put  a “string” between double quotes.结果是对的,但是如果去匹配“"string one” and “string two””则得到的结果会是 “string one” and “string two” 。这不是我们要的结果。

所以这里我们可以用否定字符集来代替“[^”/r/n]*”

3.1.10用 “|”表示选择

前面已经讲过,用字符集可以匹配很多字符其中的一个,替换的作用稍有不同。

如果需要匹配 cat 或者 dog,可以这样写:cat|dog,也可以添加很多:cat|dog|mouse|fish。

但是注意:“|”是正则表达式中优先级最低的操作符。Regex解释器在匹配的时候,要么匹配“|”左边的所有,要么匹配“|”右边的所有。

3.1.11用 “()”表示分组

可以使用圆括号来限制选择的范围。

上面的例子,如果想要限制替换,可以使用“()”符号。

比如:

如果我们要匹配整个词而不是一个词的一部分。Regex可以这样写:/b(cat|dog)/b。

这告诉regex解释器先去寻找一个边界,然后要么是cat,要么是dog,然后在去寻找一个边界。如果忽略掉括号,regex解释器会这样来匹配:要么是cat跟在一个边界的后面,要么是dog后面有一个边界。

3.1.12 “?”的补充说明

除了表示重复之外,还表示可选。

例如:colou?r,会匹配color和colour。

用括号括起来的表示这組是一个可选的项目。

例如:Nov(ember)?会匹配Nov和November。

 

用“?”标记起来,等于告诉regex解释器有两种选项:要么匹配括起来的,要么不匹配。但是,Regex解释器总会首先去匹配括起来的部分,只有当这个失败了,才会当做忽略处理。

效果就是,如果用Feb 23(rd)?去匹配Today is Feb 23rd, 2004,结果总是Feb 23rd,而不是Feb 23。

 “也称作懒元字符”,因为它总是尽可能的少的去匹配。

3.1.13给正则表达式添加注释

可以这样给正则表达式添加注释:

(?#comment here)

3.1.14操作符的运算优先级

Symbol

Function

Memo

/

转义符

 

(), (?:), (?=), []

括号

 

*, +, ?, {n}, {n,}, {n,m}

限定符

 

^, $, /anymetacharacter

定位符

 

|

 

 

3.2 高级话题

这里会讨论一些稍微复杂一些的主题,比如backreference(反向引用),lookround,ifelsethen等等。

3.2.1反向引用

()除了把regex括起来以外,还可以创建反向引用。对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '/n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。   可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对相关匹配的保存。

例如:

Set(Value)?会匹配Set和SetValue。第一种情况下,/1的反向引用会是空,因为set没有匹配value。第二种情况下,/1的反向引用的值会变为value。

如果不想创建反向引用,可以使用特殊符号“:”,比如Set(?:Value)?。

使用反向引用

例如:我们要匹配一个html标记,和两个标记之间的内容。

我们可以这样写:<([A-Z][A-Z0-9]*)[^>]*>.*?<//1>。

首先创建一个[A-Z][A-Z0-9]的引用,然后后面用到这个引用。

注意:引用中不能引用自己。

 

正则表达式一个最重要的特性就是将匹配成功的模式的某部分进行存储供以后使用这一能力。请回想一下,对一个正则表达式模式或部分模式两边添加圆括号将导致这部分表达式存储到一个临时缓冲区中。可以使用非捕获元字符 '?:', '?=', or '?!' 来忽略对这部分正则表达式的保存。

所捕获的每个子匹配都按照在正则表达式模式中从左至右所遇到的内容存储。存储子匹配的缓冲区编号从 1 开始,连续编号直至最大 99 个子表达式。每个缓冲区都可以使用 '/n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。

反向引用一个最简单,最有用的应用是提供了确定文字中连续出现两个相同单词的位置的能力。请看下面的句子:

Is is the cost of of gasoline going up up?

根据所写内容,上面的句子明显存在单词多次重复的问题。如果能有一种方法无需查找每个单词的重复现象就能修改该句子就好了。下面的正则表达式就可以实现这一功能。

/b([a-z]+) /1/b

在这个示例中,子表达式就是圆括号之间的每一项。所捕获的表达式包括一个或多个字母字符,即由[a-z]+ 所指定的。该正则表达式的第二部分是对前面所捕获的子匹配的引用,也就是由附加表达式所匹配的第二次出现的单词。'/1'用来指定第一个子匹配。单词边界元字符确保只检测单独的单词。如果不这样,则诸如 "is issued" 或 "this is" 这样的短语都会被该表达式不正确地识别。

3.2.2在正则表达式中指定模式option

可以在正则表达式中指定匹配模式

Symbol

Function

Memo

i

区分大小写

前面加“-”表示关闭选项

s

单行模式匹配

 

M

多行模式匹配

 

 

语法为(?ism)

可以只对表达式的一部分使用模式,有效范围为从这个位置起直到碰到下一个模式符为止。

也可以在前面加上“-”表示关闭这个选项。

比如(?i-sm),表示区分大小写,关闭单行模式,打开多行模式。

3.2.3 Lookaround断言

Perl5新引进了一种构造,分别为Lookahead和Lookbeehind。它们也被称作“0宽度断言”。说它们是“0宽度”是因为它们和定位符差不多,都匹配的是一行或一个词的开始或结束。不同的地方是Lookahaed和Lookbehind匹配的是一个字符,而不是一个位置,但是却返回的不是匹配的字符结果,而是返回匹配的结果:匹配还是不匹配。这也是为什么称作它们是“断言”。它们不关心匹配结果是什么,它们只用来断言这个匹配结果有没有可能。

正向和反向的Lookahead

正向Lookahead的语法为:(?=Regex)

反向Lookahead的语法为:(?!Regex)

前面我们的例子q[^u]表示的意义是:‘q’后面的字符可以是除了u以外的所有字符”。但是,如果我们要得到的结果是:‘q’后面不是’u’,注意,不是:’q’后面的字符不是’u’。(q后面可以什么也没有,而字符集必须匹配一个字符),在这种情况下,我们就必须使用反向lookahead断言。可以这样写:q(?!u)。它的匹配结果就是: ‘q’后面不是’u’。

正向lookahead断言q(?=u)匹配的结果就是:‘q’后面是’u’。

重要:

可以在lookahead中使用任何合法的正则表达式,但是在lookbehind中就不可以。

Lookahead虽然被()括起来,但它并不创建反向引用。如果想要把断言中的匹配结果存起来,必须单独使用(),像这样:(?=(regex))。

 

正向和反向的Lookbehind

正向Lookbehind的语法为:(?<=Regex)

反向Lookbehind的语法为:(?<!Regex)

用’<’来区分是Lookahead还是Lookbehind。

 

Lookbehind和lookahead有作用是相同的,但是它作用在string后面。它告诉Regex解释器暂时跳过lookbehind,先去匹配lookbehind后面的是否匹配,如果后面的匹配了,才去检查lookbehind中的断言。

(?<!a)b会匹配:’b’前面不是’a’。它不会匹配cab,但是会匹配一个单独的’b’或者bed、debt。

(?<=a)会匹配cab,但是不会匹配bed和debt。

重要:

不可以在Lookbehind中就不可以。

Lookbehind必须是定长的。所以‘?’‘*’‘+’不可以使用。


4. 正则表达式基本语法索引

Regular Expression Basic Syntax Reference

Characters

Character

Description

Example

Any character except [/^$.|?*+()

All characters except the listed special characters match a single instance of themselves.

a matches a

/ (backslash) followed by any of [/^$.|?*+()

A backslash escapes special characters to suppress their special meaning.

/+ matches +

/xFF where FF are 2 hexadecimal digits

Matches the character with the specified ASCII/ANSI value, which depends on the code page used. Can be used in character classes.

/xA9 matches © when using the Latin-1 code page.

/n, /r and /t

Match an LF character, CR character and a tab character respectively. Can be used in character classes.

/r/n matches a DOS/Windows CRLF line break.

Character Classes or Character Sets [abc]

Character

Description

Example

[ (opening square bracket)

Starts a character class. A character class matches a single character out of all the possibilities offered by the character class. Inside a character class, different rules apply. The rules in this section are only valid inside character classes. The rules outside this section are not valid in character classes, except /n, /r, /t and /xFF

 

Any character except ^-]/ add that character to the possible matches for the character class.

All characters except the listed special characters.

[abc] matches a, b or c

/ (backslash) followed by any of ^-]/

A backslash escapes special characters to suppress their special meaning.

[/^/]] matches ^ or ]

- (hyphen) except immediately after the opening [

Specifies a range of characters. (Specifies a hyphen if placed immediately after the opening [)

[a-zA-Z0-9] matches any letter or digit

^ (caret) immediately after the opening [

Negates the character class, causing it to match a single character not listed in the character class. (Specifies a caret if placed anywhere except after the opening [)

[^a-d] matches x (any character except a, b, c or d)

/d, /w and /s

Shorthand character classes matching digits 0-9, word characters (letters and digits) and whitespace respectively. Can be used inside and outside character classes

[/d/s] matches a character that is a digit or whitespace

/D, /W and /S

Negated versions of the above. Should be used only outside character classes. (Can be used inside, but that is confusing).)

/D matches a character that is not a digit

Dot

Character

Description

Example

. (dot)

Matches any single character except line break characters /r and /n. Most regex flavors have an option to make the dot match line break characters too.

. matches x or (almost) any other character

Anchors

Character

Description

Example

^ (caret)

Matches at the start of the string the regex pattern is applied to. Matches a position rather than a character. Most regex flavors have an option to make the caret match after line breaks (i.e. at the start of a line in a file) as well.

^. matches a in abc/ndef. Also matches d in "multi-line" mode.

$ (dollar)

Matches at the end of the string the regex pattern is applied to. Matches a position rather than a character. Most regex flavors have an option to make the dollar match before line breaks (i.e. at the end of a line in a file) as well. Also matches before the very last line break if the string ends with a line break.

.$ matches f in abc/ndef. Also matches c in "multi-line" mode.

/A

Matches at the start of the string the regex pattern is applied to. Matches a position rather than a character. Never matches after line breaks.

/A. matches a in abc

/Z

Matches at the end of the string the regex pattern is applied to. Matches a position rather than a character. Never matches before line breaks, except for the very last line break if the string ends with a line break.

./Z matches f in abc/ndef

/z

Matches at the end of the string the regex pattern is applied to. Matches a position rather than a character. Never matches before line breaks.

./z matches f in abc/ndef

Word Boundaries

Character

Description

Example

/b

Matches at the position between a word character (anything matched by /w) and a non-word character (anything matched by [^/w] or /W) as well as at the start and/or end of the string if the first and/or last characters in the string are word characters.

./b matches c in abc

/B

Matches at the position between two word characters (i.e the position between /w/w) as well as at the position between two non-word characters (i.e. /W/W).

/B./B matches b in abc

Alternation

Character

Description

Example

| (pipe)

Causes the regex engine to match either the part on the left side, or the part on the right side. Can be strung together into a series of options.

abc|def|xyz matches abc, def or xyz

| (pipe)

The pipe has the lowest precedence of all operators. Use grouping to alternate only part of the regular expression.

abc(def|xyz) matches abcdef or abcxyz

Quantifiers

Character

Description

Example

? (question mark)

Makes the preceding item optional. Greedy, so the optional item is included in the match if possible.

abc? matches ab or abc

??

Makes the preceding item optional. Lazy, so the optional item is excluded in the match if possible. This construct is often excluded from documentation because of its limited use.

abc?? matches ab or abc

* (star)

Repeats the previous item zero or more times. Greedy, so as many items as possible will be matched before trying permutations with less matches of the preceding item, up to the point where the preceding item is not matched at all.

".*" matches "def" "ghi" in abc "def" "ghi" jkl

*? (lazy star)

Repeats the previous item zero or more times. Lazy, so the engine first attempts to skip the previous item, before trying permutations with ever increasing matches of the preceding item.

".*?" matches "def" in abc "def" "ghi" jkl

+ (plus)

Repeats the previous item once or more. Greedy, so as many items as possible will be matched before trying permutations with less matches of the preceding item, up to the point where the preceding item is matched only once.

".+" matches "def" "ghi" in abc "def" "ghi" jkl

+? (lazy plus)

Repeats the previous item once or more. Lazy, so the engine first matches the previous item only once, before trying permutations with ever increasing matches of the preceding item.

".+?" matches "def" in abc "def" "ghi" jkl

{n} where n is an integer >= 1

Repeats the previous item exactly n times.

a{3} matches aaa

{n,m} where n >= 1 and m >= n

Repeats the previous item between n and m times. Greedy, so repeating m times is tried before reducing the repetition to n times.

a{2,4} matches aa, aaa or aaaa

{n,m}? where n >= 1 and m >= n

Repeats the previous item between n and m times. Lazy, so repeating n times is tried before increasing the repetition to m times.

a{2,4} matches aaaa, aaa or aa

{n,} where n >= 1

Repeats the previous item at least n times. Greedy, so as many items as possible will be matched before trying permutations with less matches of the preceding item, up to the point where the preceding item is matched only n times.

a{2,} matches aaaaa in aaaaa

{n,}? where n >= 1

Repeats the previous item between n and m times. Lazy, so the engine first matches the previous item n times, before trying permutations with ever increasing matches of the preceding item.

a{2,}? matches aa in aaaaa

 


5.   正则表达式高级语法索引

Regular Expression Advanced Syntax Reference

Grouping and Backreferences

Syntax

Description

Example

(regex)

Round brackets group the regex between them. They capture the text matched by the regex inside them that can be reused in a backreference, and they allow you to apply regex operators to the entire grouped regex.

(abc){3} matches abcabcabc. First group matches abc.

(?:regex)

Non-capturing parentheses group the regex so you can apply regex operators, but do not capture anything and do not create backreferences.

(?:abc){3} matches abcabcabc. No groups.

/1 through /9

Substituted with the text matched between the 1st through 9th pair of capturing parentheses. Some regex flavors allow more than 9 backreferences.

(abc|def)=/1 matches abc=abc or def=def, but not abc=def or def=abc.

Modifiers

Syntax

Description

Example

(?i)

Turn on case insensitivity for the remainder of the regular expression. (Older regex flavors may turn it on for the entire regex.)

te(?i)st matches teST but not TEST.

(?-i)

Turn off case insensitivity for the remainder of the regular expression.

(?i)te(?-i)st matches TEst but not TEST.

(?s)

Turn on "dot matches newline" for the remainder of the regular expression. (Older regex flavors may turn it on for the entire regex.)

 

(?-s)

Turn off "dot matches newline" for the remainder of the regular expression.

 

(?m)

Caret and dollar match after and before newlines for the remainder of the regular expression. (Older regex flavors may apply this to the entire regex.)

 

(?-m)

Caret and dollar only match at the start and end of the string for the remainder of the regular expression.

 

(?i-sm)

Turns on the options "i" and "m", and turns off "s" for the remainder of the regular expression. (Older regex flavors may apply this to the entire regex.)

 

(?i-sm:regex)

Matches the regex inside the span with the options "i" and "m" turned on, and "s" turned off.

(?i:te)st matches TEst but not TEST.

Atomic Grouping and Possessive Quantifiers

Syntax

Description

Example

(?>regex)

Atomic groups prevent the regex engine from backtracking back into the group (forcing the group to discard part of its match) after a match has been found for the group. Backtracking can occur inside the group before it has matched completely, and the engine can backtrack past the entire group, discarding its match entirely. Eliminating needless backtracking provides a speed increase. Atomic grouping is often indispensable when nesting quantifiers to prevent a catastrophic amount of backtracking as the engine needlessly tries pointless permutations of the nested quantifiers.

x(?>/w+)x is more efficient than x/w+x if the second x cannot be matched.

?+, *+, ++ and {m,n}+

Possessive quantifiers are a limited yet syntactically cleaner alternative to atomic grouping. Only available in a few regex flavors. They behave as normal greedy quantifiers, except that they will not give up part of their match for backtracking.

x++ is identical to (?>x+)

Lookaround

Syntax

Description

Example

(?=regex)

Zero-width positive lookahead. Matches at a position where the pattern inside the lookahead can be matched. Matches only the position. It does not consume any characters or expand the match. In a pattern like one(?=two)three, both two and three have to match at the position where the match of one ends.

t(?=s) matches the second t in streets.

(?!regex)

Zero-width negative lookahead. Identical to positive lookahead, except that the overall match will only succeed if the regex inside the lookahead fails to match.

t(?!s) matches the first t in streets.

(?<=text)

Zero-width positive lookbehind. Matches at a position to the left of which text appears. Since regular expressions cannot be applied backwards, the test inside the lookbehind can only be plain text. Some regex flavors allow alternation of plain text options in the lookbehind.

(?<=s)t matches the first t in streets.

(?<!text)

Zero-width negative lookbehind. Matches at a position if the text does not appear to the left of that position.

(?<!s)t matches the second t in streets.

Continuing from The Previous Match

Syntax

Description

Example

/G

Matches at the position where the previous match ended, or the position where the current match attempt started (depending on the tool or regex flavor). Matches at the start of the string during the first match attempt.

/G[a-z] first matches a, then matches b and then fails to match in ab_cd.

Conditionals

Syntax

Description

Example

(?(?=regex)then|else)

If the lookahead succeeds, the "then" part must match for the overall regex to match. If the lookahead fails, the "else" part must match for the overall regex to match. Not just positive lookahead, but all four lookarounds can be used. Note that the lookahead is zero-width, so the "then" and "else" parts need to match and consume the part of the text matched by the lookahead as well.

(?(?<=a)b|c) matches the second b and the first c in babxcac

Comments

Syntax

Description

Example

(?#comment)

Everything between (?# and ) is ignored by the regex engine.

a(?#foobar)b matches ab

 

6.   参考资料

正则表达式库 http://www.regexlib.com/

正则表达式 Blog http://blogs.regexadvice.com/

Mastering Regular Expressions (O'Reilly),作者 Jeffrey Friedl http://www.regex.info/

.NET 正则表达式参考

 http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemTextRegularExpressions.asp

Jscript 正则表达式语法

http://www.msdn.microsoft.com/library/en-us/script56/html/js56jsgrpRegExpSyntax.asp

正则表达式信息 http://www.regular-expressions.info/

7.   推荐工具

本文所有的例子都是在EditPad Pro下验证的。

这个工具做的很好,有语法检查和高亮显示功能,对写出正确的表达式很有帮助。极力推荐J

下载地址:http://www.editpadpro.com/

 

另一个工具是:The Regulator.

这个工具是针对。NET平台的,用的是.NET实现的正则表达式类库。如果要在.NET中验证表达式,这个工具不可或缺。

下载地址:http://royo.is-a-geek.com/iserializable/regulator/

 

也可以在这里找到://xafile/Share/Public/Bond/Regex

Regular Expressions (2) ---- Common Used Samples

 说明:

以下所有的例子都在EditPad Pro下经过验证,如果不能用,可能和特定的解释引擎有关,稍稍修改就可以了。J (看得头都晕了~~)

更多的例子:http://www.regexlib.com

 

 

电子邮件验证... 2

简单验证电子邮件地址... 2

标准验证电子邮件地址... 2

数字验证... 2

大于零的Decimal数字... 2

任何Decimal数字... 2

0-99999999的带或不带逗号的数字... 3

0-65535的值... 3

字符串验证... 3

HTML和XML表姐... 3

ISBN格式的字符串... 3

GUID. 4

信用卡号... 4

连在一起的两个相同的单词... 4

双引号括起来的词... 4

标记... 5

验证html中的16位颜色值... 5

验证包含JSP事件的html代码... 5

验证一对封闭的xml标记... 5

验证HTML中所有合法的on事件... 5

查找html中的注释... 6

查找html中的特定文件(swf.jpg.gif…)... 6

日期和时间验证... 6

日期验证... 6

日期和时间验证... 6

标准ANSI SQL日期验证... 7

其他... 7

匹配字体... 7

匹配MD5哈西字符串... 7

 


电子邮件验证

简单验证电子邮件地址

表达式

(/w[-._/w]*/w@/w[-._/w]*/w/./w{2,3})

描述

简单符合<name>@xxx.com即可。

粗略验证

匹配的例子

[foo@bar.com], [foobar@foobar.com.au]

不匹配的例子

[foo@bar], [$$$@bar.com]

 

标准验证电子邮件地址

表达式

^(([^<>;()[/]//.,;:@"]+(/.[^<>()[/]//.,;:@"]+)*)|(".+"))@((([a-z]([-a-z0-9]*[a-z0-9])?)|(#[0-9]+)|(/[((([01]?[0-9]{0,2})|(2(([0-4][0-9])|(5[0-5]))))/.){3}(([01]?[0-9]{0,2})|(2(([0-4][0-9])|(5[0-5]))))/]))/.)*(([a-z]([-a-z0-9]*[a-z0-9])?)|(#[0-9]+)|(/[((([01]?[0-9]{0,2})|(2(([0-4][0-9])|(5[0-5]))))/.){3}(([01]?[0-9]{0,2})|(2(([0-4][0-9])|(5[0-5]))))/]))$

描述

所有符合RFC 821(http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc0821.html#page-30)规定的格式的邮件地址

匹配的例子

blah@[10.0.0.1]|||a@b.c

不匹配的例子

non@match@.

数字验证

大于零的Decimal数字

表达式

(^/d*/.?/d*[1-9]+/d*$)|(^[1-9]+/d*/./d*$)

描述

大于零的Decimal数字

匹配的例子

0.050

5.0000

5000

不匹配的例子

0

0.0

.0

 

任何Decimal数字

表达式

^(/d|-)?(/d|,)*/.?/d*$

描述

匹配:

纯数字

负数

逗号分割的数字

点分割的decimal格式

匹配的例子

5,000

-5,000

100.044

.2

不匹配的例子

abc

1.3.4

 

0-99999999的带或不带逗号的数字

表达式

^(/d|-)?(/d|,)*/.?/d*$

描述

匹配:

0-99999999的带或不带逗号的数字

匹配的例子

5,000

100044

不匹配的例子

123,888,888

1.1

 

0-65535的值

表达式

^([0-5]?/d?/d?/d?/d|6[0-4]/d/d/d|65[0-4]/d/d|655[0-2]/d|6553

[0-5])$

描述

0-65535数字

匹配的例子

5000

100

不匹配的例子

66666

-2

字符串验证

HTML和XML标记

表达式

<[^>]+>

描述

所有的html和xml标记

匹配的例子

<b>

</b>

5.0000

5000

不匹配的例子

http://www.regexlib.com/Add.aspx

 

ISBN格式的字符串

表达式

<[^>]+>

描述

ISBN格式的字符串。

详细定义:http://www.isbn.org/standards/home/isbn/international/html/usm4.htm

 

匹配的例子

ISBN 0 93028 923 4

ISBN 1-56389-668-0

ISBN 1-56389-016-X

不匹配的例子

http://www.regexlib.com/Add.aspx

 

GUID

表达式

^[{|/(]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[/)|}]?$

描述

以下格式的32位GUID:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}

(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)

匹配的例子

914D226A-2F5B-4944-934D-96BBE6571977

{914D226A-2F5B-4944-934D-96BBE6571977}

不匹配的例子

914D226A-2F5B-4944-XXXX-96BBE6571977

{914D226A-2F5B-4944-XXXX-96BBE6571977}

 

信用卡号

表达式

^[{|/(]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[/)|}]?$

描述

16位数字

16位数字用连字符或者空格或者分割

匹配的例子

1234343425262837

1111-2323-2312-3434

1111 2323 2312 3434

不匹配的例子

1111 2323 2312-3434

 

连在一起的两个相同的单词

表达式

(/w+)/s+/1

描述

验证连在一起的两个相同的单词

匹配的例子

abc abc

不匹配的例子

abc abcd

 

双引号括起来的词

表达式

"((//")|[^"(//")])+"

描述

验证用双引号括起来的词

匹配的例子

“Abc”

“abc”sff”

不匹配的例子

“sdfsdfsdf

标记

验证html中的16位颜色值

表达式

 

^#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$

 

描述

验证html中的16进制的颜色值

#是可选的。

匹配的例子

#00ccff

ffffcc

不匹配的例子

blue

0x000000

 

验证包含JSP事件的html代码

表达式

<[a-zA-Z][^>]*/son/w+=(/w+|'[^']*'|"[^"]*")[^>]*>

描述

验证包含JSP事件的html代码

匹配的例子

<IMG onmouseover="window.close()">

不匹配的例子

IMG src="star.gif"

 

验证一对封闭的xml标记

表达式

 

^#?([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?$

 

描述

验证一对括起来的xml标记。

匹配的例子

<body> text<br/>More Text </body>

<a href="link.html">Link</a>

不匹配的例子

blue

0x000000

 

验证HTML中所有合法的on事件

表达式

(?i:on(blur|c(hange|lick)|dblclick|focus|keypress|(key|mouse

)(down|up)|(un)?load|mouse(move|o(ut|ver))|reset|s(elect|ubm

it)))

描述

验证HTML中所有合法的on事件

匹配的例子

onclick

onmouseover

不匹配的例子

Click

Move

 

查找html中的注释

表达式

<!/-/-.*?/-/->

描述

查找html中的注释

匹配的例子

<!-- <h1>this text has been removed</h1> -->

不匹配的例子

<h1>this text has been removed</h1>

 

查找html中的特定文件(swf.jpg.gif…)

表达式

<[^>]*/n?.*=("|')?(.*/.jpg)("|')?.*/n?[^<]*>

描述

查找html中的特定文件(swf.jpg.gif…)

把jpg换为gif,即是查找所有的gif文件。

匹配的例子

<td background="../img/img.jpg" >

不匹配的例子

= img.jpg

日期和时间验证

日期验证

表达式

^(?:(?:(?:(?:(?:1[6-9]|[2-9]/d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(//|-|/.)(?:0?2/1(?:29)))|(?:(?:(?:1[6-9]|[2-9]/d)?/d{2})(//|-|/.)(?:(?:(?:0?[13578]|1[02])/2(?:31))|(?:(?:0?[1,3-9]|1[0-2])/2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))/2(?:0?[1-9]|1/d|2[0-8]))))$

描述

验证格式为y/m/d的日期从1600/1/1 - 9999/12/31的日期

匹配的例子

04/2/29

2002-4-30

02.10.31

不匹配的例子

2003/2/29

02.4.31

00/00/00

 

日期和时间验证

表达式

^(?=/d)(?:(?:(?:(?:(?:0?[13578]|1[02])(//|-|/.)31)/1|(?:(?:0?[1,3-9]|1[0-2])(//|-|/.)(?:29|30)/2))(?:(?:1[6-9]|[2-9]/d)?/d{2})|(?:0?2(//|-|/.)29/3(?:(?:(?:1[6-9]|[2-9]/d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))|(?:(?:0?[1-9])|(?:1[0-2]))(//|-|/.)(?:0?[1-9]|1/d|2[0-8])/4(?:(?:1[6-9]|[2-9]/d)?/d{2}))($|/ (?=/d)))?(((0?[1-9]|1[012])(:[0-5]/d){0,2}(/ [AP]M))|([01]/d|2[0-3])(:[0-5]/d){1,2})?$

描述

验证所有合法的日期和时间

匹配的例子

20:20

04/2/29

02.4.31

02.10.312002-4-30

02.10.31

不匹配的例子

2003/2/29

00/00/00

 

标准ANSI SQL日期验证

表达式

^((/d{2}(([02468][048])|([13579][26]))[/-///s]?((((0?[13578])|(1[02]))[/-///s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[/-///s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[/-///s]?((0?[1-9])|([1-2][0-9])))))|(/d{2}(([02468][1235679])|([13579][01345789]))[/-///s]?((((0?[13578])|(1[02]))[/-///s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[/-///s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[/-///s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(/s(((0?[1-9])|(1[0-2]))/:([0-5][0-9])((/s)|(/:([0-5][0-9])/s))([AM|PM|am|pm]{2,2})))?$

描述

匹配ANSI SQL的日期格式:YYYY-mm-dd hh:mi:ss am/pm

包括检查从1901-2099是否是闰年。

匹配的例子

2004-2-29

2004-02-29 10:29:39 pm

2004/12/31

不匹配的例子

04-2-29

04-02-29 10:29:39 pm

04/12/31

其他

匹配字体

表达式

^(/d)(/d)*( )*(px|PX|Px|pX|pt|PT|Pt|pT|)$

描述

查找字体的后缀

 

匹配的例子

1px

100 PT

20Px

不匹配的例子

1abc

px

1 sdfs

 

匹配MD5哈西字符串

表达式

^(/d)(/d)*( )*(px|PX|Px|pX|pt|PT|Pt|pT|)$

描述

^([a-z0-9]{32})$

匹配的例子

790d2cf6ada1937726c17f1ef41ab125

不匹配的例子

790D2CF6ADA1937726C17F1EF41AB125

Regex的相关工具和word文档可以在这里找到。://xafile/Share/Public/Bond/Regex

 

 

PS:

这个列表会一直更新的,希望大家也能多多支持。把看到的有用的Regex都贴进来。

J

Regular Expressions (3) ---- Using Regex in .NET

 

看这篇文章之前,假定你已经了解了有关正则表达式的一些知识,并且知道如何去应用它。本篇文章只介绍如何在.NET中使用正则表达式。

 最后是一个应用正则表达式的给VB程序语法加亮的小程序。

 

 

 

名称空间和相关的类

.NET中所有和正则表达式相关的类都定义在System.Text.RegularExpressions名称空间下。

分别是:

Class

Description

Regex

不可变的(只读)的正则表达式的实例,包括一些静态方法

Capture

包含单个子表达式匹配的结果,不能实例化,必须通过Group和Match来访问。

CaptureCollection

Capture的序列

Group

一组表达式匹配的结果,由Capture继承而来

GroupCollection

Group的序列

Match

一个正则表达式的匹配结果,由Group继承而来

MatchCollection

Match的序列

 下面用图和例子说明各个类之间的关系:

例:

 

 

 

如上图:

匹配的字符串是:”xgraygreyxgreyxgray”

正则表达式是:(gr[ae])y

表示匹配”gray”或者”grey”一次或n次。

 从生成的匹配树可以看到:

总共找到了三个匹配。每个匹配的值分别为:graygray,gray,grey。

以第一个匹配为例:

匹配一中共包括两个组:每个组的值分别为:graygrey,grey。

第一个组只有一个捕获结果,就是graygrey。

第二组有两个捕获结果,分别为gray和grey。

 

下面说明这些类的详细作用:

Match

Match表示的是一个正则表达式的匹配操作。

如上例:

 

(Gr[ae]y)+得到三个Match结果。分别是graygrey,gray,grey。

这等于是正则表达式解释器把(gr[ae]y)+吃拆成了(gr[ae]y)+,(gray)+和(grey)+三个单独的子表达式。

每个子表达式对应一个Match结果。

Regex

Result

(gr[ae]y)+

Graygrey

(gray)+

Gray

(grey)+

Grey

 

MatchCollection

MatchCollection表示的就是所有的字表达式的Match结果的集合。

可以通过遍历Matchs的集合来访问各个子表达式的Match结果。

For each m as Match in Regex.Matches(“graygrey”, (gr[ae]y)+”)

            ‘ Use match result here.

Next

 

Group

每个子表达式默认就是一个组。所以子表达式的所有组的结果都保存在第一个组中,这也是为什么每个Match的结果和第一个Group的结果是一样的,因为它们就是一个。

 

在.NET中,用括号括起来的子表达式表示这是一个组。

可以通过(?<groupName><子表达式>)来显示的给组命名。

 

比如:

Regex r = new Regex(“(?abc)+”)。就定义了一个组,名字为g1。

在程序中,我们可以通过组命来访问组的匹配结果。

Dim m As Match = r.Match("xxabcabc")

Dim g1 As Group = m.Groups(“g1”)

 

GroupCollection

GroupCollection表示一个Match中Group的集合。

可以通过组命或者索引来访问一个组。

 Catpure

Capture中保存的是每一个子表达式的最小匹配结果,它相当于是原子匹配,比如a匹配a,则结果a就保存在capture中,group的结果只是所的capture结果的组合。

所以如果一个匹配只有一个group,这个group中又只有一个capture,则这个capture的结果就是整个Match的结果。

 

CaptureCollection

Capture的序列。

 

VBHightDemo

下面介绍一下这个应用正则表达式给VB语法加亮的程序。

这个程序的原理就是根据正则表达式分析每一行字符串,根据匹配结果,把相应的字符的颜色改变。

 

关键的地方就是拿到组建的正则表达式。

Private VBImports As Regex = New Regex("(?RegexOptions.Compiled)

    Private QuotedString As Regex = New Regex("""" & "[^""]*" & """", RegexOptions.Compiled)

    Private VBComment As Regex = New Regex("'.*")

    Private EmptyLine As Regex = New Regex("^//s*//Z", RegexOptions.Compiled)

    Private VBRegion As Regex = New Regex("(#region|#end region){1}", RegexOptions.Compiled)

     '-- use lookbehind, keywords can not follow by a '.' or a characotr

    Dim aa As String = "(?<![/./w])(as|boolean|break|byte|byval|byref|" _

                                & "case|catch|char|checked|class|const|continue|" _

                                & "decimal|dim|default|delegate|double|else|" _

                                & "enum|end|event|exit|explicit|extern|false|each|" _

                                & "float|friend|for|goto|if|implicit|inherits|" _

                                & "integer|interface|internal|is|lock|long|" _

                                & "namespace|new|next|overrides|overloads|object|operator|out|" _

                                & "override|params|private|protected|" _

                                & "public|readonly|ref|return|sbyte|sealed|" _

                                & "short|static|string|sub|" _

                                & "structure|switch|me|mybase|throw|true|try|typeof|" _

                                & "uint|ulong|unchecked|ushort|using|" _

                                & "while|withevents){1}[^/w]"

    Private VBKeyWords As Regex = New Regex(aa, RegexOptions.Compiled)

 

    Private SystemKeyWords As Regex = New Regex("(application|console|environment|gc|threadpool|math){1}", RegexOptions.Compiled)

Private Brackets As Regex = New Regex("(/{|/[|/(|/}|/]|/))", RegexOptions.Compiled)

 

在匹配的时候,可以给指定匹配的选项,比如忽略大小写,单行还是多行等等。

然后遍历并加亮匹配的结果就可以了。

For Each m As Match In regex.Matches(s)

       Me.ColorString(start + m.Groups(0).Index, m.Groups(0).Length, color)

Next

 

因为组中保存的就是所有capture的组合的结果,所以只加亮groups(0)中的字符串就够了,不需要再重复处理group中captures的值。

 

不正之处还请多多指正。

:)

posted on 2014-12-01 11:14  狂狗A地板  阅读(504)  评论(0编辑  收藏  举报

导航