快速學習正則表達式

正則表達式 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”    

 

發佈了23 篇原創文章 · 獲贊 1 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章