快速学习正则表达式

正则表达式 Regular Expression ,缩写为 regexp regex regxp ) ,又称正规表达式正规表示式常规表达式 是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和 / 或替换那些符合某个 模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在 Perl 中就内建了一个功能强大的在正则表达式引擎。正则表达式这个概念 最初是由 Unix 中的工具软件(例如 sed grep )普及开的。

====================

基本概念

正则表达式也经常被称为模式 ,用来描述或者匹配一系列符合某个句法规则的字符串。例如, Handel Händel ,和 Haendel 三个字符串,都可以由 "H(a|ä|ae)ndel" 这个模式来描述。大部分形式都有如下的结构:

替换  

|         竖直分隔符代表替换。例如 "gray|grey" 可以匹配 grey gray  

数量限定  

某个字符后的数量限定符用来限定前面这个字符允许出现的个数。最常见的数量限定符包括 +, ?, * (不加数量限定则代表出现一次且仅出现一次):  

+         加号代表前面的字符必须至少出现一次。 (1 次,或多次 ) 。例如, "goo+gle" 可以匹配 google gooogle goooogle

?         问号代表前面的字符最多只可以出现一次。 (0 次,或 1 ) 。例如, "colou?r" 可以匹配 colour 或者 color

*         星号代表前面的字符可以不出现,也可以出现一次或者多次。 (0 次,或 1 次,或多次 ) 。例如, "0*42" 可以匹配 42 042 0042 00042 等。  

捕获  

圆括号可以用来定义操作符的范围和优先度。例如, "gr(a|e)y" 等价于 "gray|grey" "(grand)?father" 匹配 father grandfather  

上述这些构造子都可以自由组合,因此, "H(ae?|ä)ndel" "H(a|ae|ä)ndel" 是相同的。

精确的语法可能因不同的工具和程序而异。

====================

正则表达式语法  

正则表达式是一种文本模式,包括普通字符(例如,  z  之间的字母)和特殊字符(称为 元字符 )。模式描述在搜索文本时要匹配的一个或多个字符串。

下面是正则表达式的一些示例:

表达式

匹配

/^/s*$/

匹配空行。

//d{2}-/d{5}/

验证由两位数字、一个连字符再加  5  位数字组成的  ID  号。

/</s*(/S+)(/s[^>]*)?>[/s/S]*</s*///1/s*>/

匹配  HTML  标记。

下表包含了元字符的完整列表以及它们在正则表达式上下文中的行为:

字符

说明

/

将下一字符标记为特殊字符、文本、反向引用或八进制转义符。例如, “n” 匹配字符 “n” “/n” 匹配换行符。序列 “//” 匹配 “/” “/(” 匹配 “(”

^

匹配输入字符串开始的位置。如果设置了  RegExp   对象的  Multiline   属性, 还会与 “/n” “/r” 之后奈恢闷ヅ洹 ?/td> 

$

匹配输入字符串结尾的位置。如果设置了  RegExp   对象的  Multiline   属性, 还会与 “/n” “/r” 之前的位置匹配。

*

零次或多次匹配前面的字符或子表达式。例如, zo*  匹配 “z” “zoo” 等效于  {0,}

+

一次或多次匹配前面的字符或子表达式。例如, “zo+” “zo” “zoo” 匹配,但与 “z” 不匹配。 等效于  {1,}

?

零次或一次匹配前面的字符或子表达式。例如, “do(es)?” 匹配 “do” “does” 中的 “do” 等效于  {0,1}

{n }

是非负整数。正好匹配  n   次。例如, “o{2}” “Bob” 中的 “o” 不匹配,但与 “food” 中的两个 “o” 匹配。

{n ,}

是非负整数。至少匹配   次。例如, “o{2,}” 不匹配 “Bob” 中的 “o” ,而匹配 “foooood” 中的所有  o 'o{1,}'  等效于  'o+' 'o{0,}'  等效于  'o*'

{n ,m }

m    n   是非负整数,其中  n  <= m 。至少匹配  n   次,至多匹配  m   次。例如, “o{1,3}” 匹配 “fooooood” 中的头三个  o 'o{0,1}'  等效于  'o?' 。注意:您不能将空格插入逗号和数字之间。

?

当此字符紧随任何其他限定符( * + ? {n } {n ,} {n ,m } )之后时,匹配模式是 非贪心的 非贪心的 模式匹配搜索到的、尽可能短的字符串,而默认的 贪心的 模式匹配搜索到的、尽可能长的字符串。例如,在字符串 “oooo” 中, “o+?” 只匹配单个 “o” ,而 “o+” 匹配所有 “o”

.

匹配除 “/n” 之外的任何单个字符。若要匹配包括 “/n” 在内的任意字符,请使用诸如 “[/s/S]” 之类的模式。

(pattern )

匹配  pattern   并捕获该匹配的子表达式。可以使用  $0 ...$9   属性从结果 匹配 集合中检索捕获的匹配。若要匹配括号字符  ( ) ,请使用 “/(” 或者 “/)”

(?:pattern )

匹配  pattern   但不捕获该匹配的子表达式,即它是一个非捕获匹配,不存储供以后使用的匹配。这对于用 字符  (|)  组合模式部件的情况很有用。例如,与 “industry|industries” 相比, “industr(?:y| ies)” 是一个更加经济的表达式。

(?=pattern )

执行正向预测先行搜索的子表达式,该表达式匹配处于匹配  pattern   字符串的起始点的字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如, “Windows (?=95| 98| NT| 2000)” “Windows 2000” 中的 “Windows” 匹配,但不与 “Windows 3.1” 中的 “Windows” 匹配。预测先行不占用字符,即发生匹 配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

(?!pattern )

执行反向预测先行搜索的子表达式,该表达式匹配不处于匹配  pattern   字符串的起始点的搜索字符串。它是一个非捕获匹配,即不能捕获供以后使用的匹配。例如, “Windows (?!95| 98| NT| 2000)” “Windows 3.1” 中的 “Windows” 匹配,但不与 “Windows 2000” 中的 “Windows” 匹配。预测先行不占用字符,即发生匹 配后,下一匹配的搜索紧随上一匹配之后,而不是在组成预测先行的字符后。

x y

 x     匹配。例如, “z| food” “z” “food” 匹配。 “(z| f)ood” “zood” “food” 匹配。  

[xyz ]

字符集。匹配包含的任一字符。例如, “[abc]” 匹配 “plain” 中的 “a”  

[^xyz ]

反向字符集。匹配未包含的任何字符。例如, “[^abc]” 匹配 “plain” 中的 “p”  

[a-z ]

字符范围。匹配指定范围内的任何字符。例如, “[a-z]” 匹配 “a” “z” 范围内的任何小写字母。  

[^a-z ]

反向范围字符。匹配不在指定的范围内的任何字符。例如, “[^a-z]” 匹配任何不在 “a” “z” 范围内的任何字符。  

/b

匹配一个字边界,即字与空格间的位置。例如, “er/b” 匹配 “never” 中的 “er” ,但不匹配 “verb” 中的 “er”  

/B

非字边界匹配。 “er/B” 匹配 “verb” 中的 “er” ,但不匹配 “never” 中的 “er”  

/cx

匹配由  x   指示的控制字符。例如, /cM  匹配一个  Control-M  或回车符。 x   的值必须在  A-Z   a-z  之间。如果不是这样,则假定  c  就是 “c” 字符本身。  

/d

数字字符匹配。等效于  [0-9]  

/D

非数字字符匹配。等效于  [^0-9]  

/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  等效。

/w

匹配任何字类字符,包括下划线。与 “[A-Za-z0-9_]” 等效。  

/W

任何非字字符匹配。与 “[^A-Za-z0-9_]” 等效。  

/xn

匹配  n ,此处的  n   是一个十六进制转义码。十六进制转义码必须正好是两位数长。例如, “/x41” 匹配 “A” “/x041” “/x04”&“1” 等效。允许在正则表达式中使用  ASCII  代码。

/num

匹配  num ,此处的  num   是一个正整数。到捕获匹配的反向引用。例如, “(.)/1” 匹配两个连续的相同字符。  

/n

标识一个八进制转义码或反向引用。如果  /n   前面至少有  n   个捕获子表达式,那么  n   是反向引用。否则,如果  n   是八进制数  (0-7) ,那么  n   是八进制转义码。

/nm

标识一个八进制转义码或反向引用。如果  /nm   前面至少有  nm   个捕获子表达式,那么  nm   是反向引用。如果  /nm   前面至少有  n   个捕获,那么  n   是反向引用,后面跟  m 。如果前面的条件均不存在,那么当    m   是八进制数  (0-7)  时, /nm   匹配八进制转义码  nm

/nml

 n   是八进制数  (0-3) m    l   是八进制数  (0-7)  时,匹配八进制转义码  nml

/un

匹配  n ,其中  n   是以四位十六进制数表示的  Unicode  字符。例如, /u00A9  匹配版权符号  (©)

====================

生成正则表达式

正则表达式的结构与算术表达式的结构类似。即,各种元字符和运算符可以将小的表达式组合起来,创建大的表达式。

通过在一对分隔符之间放置表达式模式的各种组件,就可以构建正则表达式。对于  JScript ,分隔符是正斜杠  (/)  字符。例如:

/expression /

在上面的示例中,正则表达式模式  (expression 存储在  RegExp   对象的  Pattern   属性中。

正则表达式的组件可以是单个字符、字符集、字符的范围、在几个字符之间选择或者所有这些组件的任何组合。

====================

优先级顺序

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。

下表从最高到最低说明了各种正则表达式运算符的优先级顺序:

运算符

说明

/

转义符

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

括号和中括号

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

限定符

^, $, /anymetacharacter, anycharacter

定位点和序列

|

替换

字符的优先级比替换运算符高,替换运算符允许 “m|food” “m” “food” 匹配。若要匹配 “mood” “food” ,请使用括号创建子表达式,从而产生 “(m|f)ood”

====================

普通字符

普通字符包括没有显式指定为元字符的所有可打印和不可打印字符。这包括所有大写和小写字母、所有数字、所有标点符号和一些其他符号。

正则表达式的最简单形式是在搜索字符串中匹配其本身的单个普通字符。例如,单字符模式,如  A ,不论出现在搜索字符串中的何处,它总是匹配字母  A 。下面是一些单字符正则表达式模式的示例:

/a/

/7/

/M/

可以将许多单字符组合起来以形成大的表达式。例如,以下正则表达式组合了单字符表达式: a  M

/a7M/

请注意,没有串联运算符。只须在一个字符后面键入另一个字符。  

====================

特殊字符

许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符 转义 ,即,将反斜杠字符  (/)  放在它们前面。下表列出了特殊字符以及它们的含义:

特殊字符

注释

$

匹配输入字符串结尾的位置。如果设置了  RegExp   对象的  Multiline   属性,那么  $  还匹配  /n   /r  前面的位置。若要匹配  $  字符本身,请使用  /$

( )

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

*

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

+

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

.

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

[ ]

标记中括号表达式的开始。若要匹配这些字符,请使用  /[   /]  

?

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

/

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

/

表示文本正则表达式的开始或结束。若要匹配  /  字符,请使用  //

^

匹配输入字符串开始处的位置,但在中括号表达式中使用的情况除外,在那种情况下它对字符集求反。若要匹配  ^  字符本身,请使用  /^

{ }

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

|

指出在两个项之间进行选择。若要匹配  |  ,请使用  /| 

====================

不可打印字符

非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符

含义

/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  等效。

====================

字符匹配

句点  (.)  匹配字符串中的各种打印或非打印字符,只有一个字符例外。这个例外就是换行符  (/n) 。下面的正则表达式匹配  aac abc acc adc  等等,以及  a1c a2c a-c   a#c

/a.c/

若要匹配包含文件名的字符串,而句点  (.)  是输入字符串的组成部分,请在正则表达式中的句点前面加反斜扛  (/)  字符。举例来说明,下面的正则表达式匹配  filename.ext

/filename/.ext/

这些表达式只让您匹配 任何 单个字符。可能需要匹配列表中的特定字符组。例如,可能需要查找用数字表示的章节标题( Chapter 1 Chapter 2  等等)。

中括号表达式

若要创建匹配字符组的一个列表,请在方括号(  ] )内放置一个或更多单个字符。当字符括在中括号内时,该列表称为 中括号表达式 。与在任何 别的位置一样,普通字符在中括号内表示其本身,即,它在输入文本中匹配一次其本身。大多数特殊字符在中括号表达式内出现时失去它们的意义。不过也有一些例 外,如:  

  • 如果  ]  字符不是第一项,它结束一个列表。若要匹配列表中的  ]  字符,请将它放在第一位,紧跟在开始  [  后面。      
  • 字符继续作为转义符。若要匹配  /  字符,请使用  //      

括在中括号表达式中的字符只匹配处于正则表达式中该位置的单个字符。以下正则表达式匹配  Chapter 1 Chapter 2 Chapter 3 Chapter 4   Chapter 5

/Chapter [12345]/

请注意,单词  Chapter   和后面的空格的位置相对于中括号内的字符是固定的。中括号表达式指定的只是匹配紧跟在单词  Chapter   和空格后面的单个字符位置的字符集。这是第九个字符位置。

若要使用范围代替字符本身来表示匹配字符组,请使用连字符  (-)  将范围中的开始字符和结束字符分开。单个字符的字符值确定范围内的相对顺序。下面的正则表达式包含范围表达式,该范围表达式等效于上面显示的中括号中的列表。

/Chapter [1-5]/

当以这种方式指定范围时,开始值和结束值两者都包括在范围内。注意,还有一点很重要,按  Unicode  排序顺序,开始值必须在结束值的前面。

若要在中括号表达式中包括连字符,请采用下列方法之一:  

  • 用反斜扛将它转义:      

[/-]

  • 将连字符放在中括号列表的开始或结尾。下面的表达式匹配所有小写字母和连字符:      

·         [-a-z]

    [a-z-]

  • 创建一个范围,在该范围中,开始字符值小于连字符,而结束字符值等于或大于连字符。下面的两个正则表达式都满足这一要求:      

·         [!--]

    [!-~]

若要查找不在列表或范围内的所有字符,请将插入符号  (^)  放在列表的开头。如果插入字符出现在列表中的其他任何位置,则它匹配其本身。下面的正则表达式匹配编号大于  5  的章节标题:

/Chapter [^12345]/

在上面的示例中,表达式在第九个位置匹配  1 2 3  5  之外的任何数字字符。这样,例如, Chapter 7  就是一个匹配项, Chapter 9  也是一个匹配项。

上面的表达式可以使用连字符  (-)  来表示:

/Chapter [^1-5]/

中括号表达式的典型用途是指定任何大写或小写字母或任何数字的匹配。下面的表达式指定这样的匹配:

/[A-Za-z0-9]/

====================

限定符

如果您不能指定构成匹配的字符的数量,那么正则表达式支持限定符的概念。这些限定符使您能够指定,为使匹配为真,正则表达式的某个给定组件必须出现多少次。

下表说明各种限定符以及它们的含义:

字符

说明

零次或多次匹配前面的字符或子表达式。例如, zo*  匹配  z   zoo 等效于  {0,}

一次或多次匹配前面的字符或子表达式。例如, zo+  匹配  zo   zoo ,但不匹配  z 等效于  {1,}

零次或一次匹配前面的字符或子表达式。例如, do(es)?  匹配  do   does  中的  do 等效于  {0,1}

{n }

是非负整数。正好匹配  n   次。例如, o{2}  不匹配  Bob  中的  o ,但匹配  food  中的两个  o

{n ,}

是非负整数。至少匹配   次。例如, o{2,}  不匹配  Bob  中的  o ,而匹配  foooood  中的所有  o o{1,}  等效于  o+ o{0,}  等效于  o*

{n ,m }

m    n   是非负整数,其中  n  <= m 。至少匹配  n   次,至多匹配  m   次。例如, o{1,3}  匹配  fooooood  中的头三个  o o{0,1}  等效于  o? 。注意:您不能将空格插入逗号和数字之间。

由于章节编号在大的输入文档中会很可能超过九,所以您需要一种方式来处理两位或三位章节编号。限定符给您这种能力。下面的正则表达式匹配编号为任何位数的章节标题:

/Chapter [1-9][0-9]*/

请注意,限定符出现在范围表达式之后。因此,它应用于整个范围表达式,在本例中,只指定从  0   9  的数字(包括  0   9 )。

这里不使用  +  限定符,因为在第二个位置或后面的位置不一定需要有一个数字。也不使用?字符,因为它将章节编号限制到只有两位数。您需要至少匹配  Chapter  和空格字符后面的一个数字。

如果您知道章节编号被限制为只有  99  章,可以使用下面的表达式来至少指定一位但至多两位数字。

/Chapter [0-9]{1,2}/

上面的表达式的缺点是,大于  99  的章节编号仍只匹配开头两位数字。另一个缺点是  Chapter 0  也将匹配。只匹配两位数字的更好的表达式如下:

/Chapter [1-9][0-9]?/

/Chapter [1-9][0-9]{0,1}/

*  ?  限定符都被称为 贪心的 ,因为它们匹配尽可能多的文本。但是,有时您只需要最小的匹配。

例如,您可能搜索  HTML  文档,以查找括在  H1  标记内的章节标题。该文本在您的文档中如下:

<H1>Chapter 1 – Introduction to Regular Expressions</H1>

下面的表达式匹配从开始小于符号  (<)  到关闭  H1  标记的大于符号  (>)  之间的所有内容。

/<.*>/

如果您只需要匹配开始  H1  标记,下面的 非贪心 表达式只匹配  <H1>

/<.*?>/

通过在  *  ?  限定符之后放置  ? ,该表达式从 贪心 表达式转换为 非贪心 表达式或者最小匹配。  

====================

定位点

本节前面的主题中的示例只涉及章节标题查找。字符串  Chapter  后面跟空格和数字的任何匹配项可能是实际章节标题,或者也可能是指向另一章的交叉引用。由于真正的章节标题总是出现在行的开始,所以设计一种方法只查找标题而不查找交叉引用可能很有用。

定位点提供该能力。定位点使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。下表包含正则表达式定位点以及它们的含义的列表:

字符

说明

^

匹配输入字符串开始的位置。如果设置了  RegExp   对象的  Multiline   属性, 还会与  /n   /r  之后的位置匹配。

$

匹配输入字符串结尾的位置。如果设置了  RegExp   对象的  Multiline   属性, 还会与  /n   /r  之前的位置匹配。

/b

匹配一个字边界,即字与空格间的位置。  

/B

非字边界匹配。

不能将限定符与定位点一起使用。由于在紧靠换行或者字边界的前面或后面不能有一个以上位置,因此不允许诸如  ^*  之类的表达式。

若要匹配一行文本开始处的文本,请在正则表达式的开始使用  ^  字符。不要将  ^  的这种用法与中括号表达式内的用法混淆。

若要匹配一行文本的结束处的文本,请在正则表达式的结束处使用  $  字符。

若要在搜索章节标题时使用定位点,下面的正则表达式匹配一个章节标题,该标题只包含两个尾随数字,并且出现在行首:

/^Chapter [1-9][0-9]{0,1}/

真正的章节标题不仅出现行的开始处,而且它还是该行中仅有的文本。它即出现在行首又出现在同一行的结尾。下面的表达式能确保指定的匹配只匹配章节而不匹配交叉引用。通过创建只匹配一行文本的开始和结尾的正则表达式,就可做到这一点。

/^Chapter [1-9][0-9]{0,1}$/

匹配字边界稍有不同,但向正则表达式添加了很重要的能力。字边界是单词和空格之间的位置。非字边界是任何其他位置。下面的表达式匹配单词  Chapter   的开头三个字符,因为这三个字符出现字边界后面:

//bCha/

/b  字符的位置是非常重要的。如果它位于要匹配的字符串的开始,它在单词的开始处查找匹配项。如果它位于字符串的结尾,它在单词的结尾处查找匹配项。例如,下面的表达式匹配单词  Chapter  中的字符串  ter ,因为它出现在字边界的前面:

/ter/b/

下面的表达式匹配  Chapter  中的字符串  apt ,但不匹配  aptitude  中的字符串  apt

//Bapt/

字符串  apt   出现在单词  Chapter   中的非字边界处,但出现在单词  aptitude   中的字边界处。对于  /B  非字边界运算符,位置并不重要,因为匹配不关心究竟是单词的开头还是结尾。  

====================

替换和分组

替换使用  |  字符来允许在两个或多个替换选项之间进行选择。例如,可以扩展章节标题正则表达式,以返回比章标题范围更广的匹配项。但是,这并不象 您可能认为的那样简单。替换匹配  |  字符两边的尽可能最大的表达式。您可能认为,下面的表达式匹配出现在行首和行尾、后面跟一个或两个数字  Chapter   Section

/^Chapter|Section [1-9][0-9]{0,1}$/

很遗憾,上面的正则表达式要么匹配行首的单词  Chapter ,要么匹配行尾的单词  Section   及跟在其后的任何数字。如果输入字符串是  Chapter 22 ,那么上面的表达式只匹配单词  Chapter 。如果输入字符串是  Section 22 ,那么该表达式匹配  Section 22

若要使正则表达式更易于控制,可以使用括号来限制替换的范围,即,确保它只应用于两个单词  Chapter    Section 。但是,括号也用于创建子表达式,并可能捕获它们以供以后使用,这一点在有关反向引用的那一节讲述。通过在上面的正则表达式的适当位置添加括号,就可以使该正则表达式匹配  Chapter 1   Section 3

下面的正则表达式使用括号来组合  Chapter   Section ,以便表达式正确地起作用:

/^(Chapter|Section) [1-9][0-9]{0,1}$/

虽然这些表达式正确发挥作用,但  Chapter| Section  两边的括号还会使得两个匹配单词中的任何一个被捕获以供将来使用。由于在上面的表达式中只有一组括号,因此,只有一个被捕获的 子匹配项 。可以通过使用  RegExp   对象的  $1-$9   属性来引用此子匹配项。

在上面的示例中,您只需要使用括号来组合单词  Chapter    Section   之间的选择。若要防止匹配被保存以备将来使用,请在括号内正则表达式模式之前放置  ?: 。下面的修改提供相同的能力而不保存子匹配项:

/^(?:Chapter|Section) [1-9][0-9]{0,1}$/

 ?:  元字符外,两个其他非捕获元字符创建被称为 预测先行 匹配的某些内容。正向预测先行使用  ?=  指定,它匹配处于括号中匹配正则表达式模式的起始点的搜索字符串。反向预测先行使用  ?!  指定,它匹配处于与正则表达式模式不匹配的字符串的起始点的搜索字符串。

例如,假设您有一个文档,该文档包含指向  Windows 3.1 Windows 95 Windows 98   Windows NT  的引 用。再进一步假设,您需要更新该文档,将指向  Windows 95 Windows 98   Windows NT  的所有引用更改  Windows 2000 。下面的正则表达式(这是一个正向预测先行的示例)匹配  Windows 95 Windows 98   Windows NT

/Windows(?=95 |98 |NT )/

找到一处匹配后,紧接着就在匹配的文本(不包括预测先行中的字符)之后搜索下一处匹配。例如,如果上面的表达式匹配  Windows 98 ,将在  Windows  之后而不是在  98  之后继续搜索。  

====================

反向引用

正则表达式的最重要功能之一是存储匹配的模式的一部分以供以后重新使用的能力。您可能想起,若在正则表达式模式或模式的一部分两侧加上括号,就会导致表达式的一部分被存储到临时缓冲区中。可以通过使用非捕获元字符  ?: ?=   ?!  来重写捕获。

每个捕获的子匹配项按照它们在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从  1  开始,最多可存储  99  个捕获的子表达式。可以使用  /n   来访问每个缓冲区,其中  n  是标识特定缓冲区的一位或两位十进制数字。

反向引用的最简单的、最有用的应用之一,是提供查找文本中两个相同的相邻单词的匹配项的能力。以下面的句子为例:

Is is the cost of of gasoline going up up?

上面的句子很显然有多个重复的单词。如果能设计一种方法定位该句子,而不必查找每个单词的重复出现,那该有多好。下面的正则表达式使用单个子表达式来实现这一点:

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

捕获的表达式,正如  [a-z]+  指定的,包括一个或多个字母。正则表达式的第二部分是对以前捕获的子匹配项的引用,即,单词的第二个匹配项正好 由括号表达式匹配。 /1  指定第一个子匹配项。字边界元字符确保只检测整个单词。否则,诸如 “is issued” “this is” 之类的词组将不能 正确地被此表达式识别。

正则表达式后面的全局标记  (g)  指示,将该表达式应用到输入字符串中能够查找到的尽可能多的匹配。表达式的结尾处的不区分大小写  (i)  标记指定不区分大小写。多行标记指定换行符的两边可能出现潜在的匹配。

使用上面的正则表达式,下面的代码可以使用子匹配项信息,将文本字符串中的两个连续相同的单词的匹配项替换为同一单词的单个匹配项:

var ss = "Is is the cost of of gasoline going up up?./n";

var re = //b([a-z]+) /1/b/gim;       //Create regular expression pattern.

var rv = ss.replace(re,"$1");   //Replace two occurrences with one.

 replace   方法内使用  $1   引用第一个保存的子匹配项。如果您有多个子匹配项,您将通过使用  $2 $3   等依次引用它们。

反向引用还可以将通用资源指示符  (URI)  分解为其组件。假定您想将下面的  URI  分解为协议( ftp http  等等)、域地址和页 / 路径:

http://msdn.microsoft.com:80/scripting/default.htm

下面的正则表达式提供该功能:

/(/w+):([^/:]+)(:/d*)?([^# ]*)/

第一个括号子表达式捕获  Web  地址的协议部分。该子表达式匹配在冒号和两个正斜杠前面的任何单词。第二个括号子表达式捕获地址的域地址部分。该 子表达式匹配不包括  /   :  字符的任何字符序列。第三个括号子表达式捕获端口号(如果指定了的话)。该子表达式匹配冒号后面的零个或多个数字。最 后,第四个括号子表达式捕获  Web  地址指定的路径和 / 或页信息。该子表达式匹配  #  或空格字符之外的一个或多个字符。

将正则表达式应用到上面的  URI ,各子匹配项包含下面的内容:  

  • RegExp.$1   包含 “http”     
  • RegExp.$2   包含 “msdn.microsoft.com”     
  • RegExp.$3   包含 “:80”     
  • RegExp.$4   包含 “/scripting/default.htm”    

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值