1. 程式人生 > >C#中正則表示式使用介紹

C#中正則表示式使用介紹


  4.4 匹配、組和捕獲

  一般表示式的一個很好的特性是可以把字元組合起來,方式與C#中的複合語句一樣。在C#中,可以通過把任意數量的語句放在花括號中的方式把它們組合在一起。其結果就像一個複合語句那樣。在一般表示式模式中,也可以把任何字元組合起來(包括元字元和轉義序列),像處理一個字元那樣處理它們。唯一的區別是要使用圓括號,而不是花括號,得到的序列成為一個組。 

  例如,模式"(an)+"定位序列an的任以重複。量詞+只應用於它前面的一個字元,但因為我們把字元組合起來了,所以它現在把重複的an作為一個單元來對待。"(an)."應用到輸入文字"bananas came to Europe late in the annals of history"上,會從bananas中選擇出anan。另一方面,如果使用an+,則將從annals中選擇ann,從bananas中選擇出兩個an。為什麼(an)+選擇的是anan,而沒有把單個的an作為一個匹配。匹配規則是不能重複的,如果有可能重複,在預設情況下就選擇較長的匹配。

  但是,組的功能要比這強大得多。在預設情況下,把模式的一部分組合為一個組時,就要求一般表示式引擎記住可以按照這個組來匹配,也可以按照整個模式來匹配。換言之,可以把組當作一個要匹配的模式,如果要把字串分解為各個部分,這種模式就是非常有效的。 
例如,URI的格式是"<protocol>://<address>:<port>",其中埠是可選的。它的一個樣例是http://www.comprg.com.cn:8080。假定要從一個URI中提取協議、地址和埠,而且緊鄰URI的後面可能有空白(但沒有標點符號),就可以使用下面的表示式:"\b(\S+)://(\S+)(?::(\S+))?\b"

  該表示式的工作方式如下:首先,前導和尾部的\b序列確保只需要考慮完全是字的文字部分,在這個文字部分中,第一組"(\S+)://"會選擇一個或多個不適空白的字元,其後是"://"。在HTTPURI的開頭會選擇出http://。花括號表示把http儲存為一個組。後面的"(\S+)"則在上述URI中選擇www. comprg.com.cn,這個組在遇到詞的結尾時或標記另一個組的冒號"(:)"時結束。

  下一個組選擇埠(本例是:8080)。後面的?表示這個組在匹配中是可選的,如果沒有:xxxx,也不會妨礙匹配的標記。

  這是非常重要的,因為埠在URI中一般不指定,實際上,在大多數情況下,URI是沒有埠號的。但是,事情會比較複雜。如果要求冒號可以出現,也可以不出現,但不希望把這個冒號也儲存在組中。為此,可以巢狀兩個組:內部的"(\S+)"組選擇冒號後面的內容(本例中是8080),外面的組包含內部的組,後面是一個冒號,該冒號又在序列"?:"的後面。這個序列表示該組不應儲存(只需要儲存"8080",不需要儲存":8080")。不要把這兩個冒號混淆了,第一個冒號是序列"?:"的一部分,表示不儲存這個組,第二個冒號是要搜尋的文字。

  在這個字串上執行該模式:I always visit http://www. comprg.com.cn 得到的匹配是http://www. comprg.com.cn。在這個匹配中,僅提到了三個組,還有第四個組表示匹配本身。理論上,每個組都可以選擇0次、1次或者多次匹配。單個的匹配就稱為捕獲。在第一個組"(\S+)",有一個捕獲http。第二個組也有一個捕獲www. comprg.com.cn,但第三個組沒有捕獲,因為在這個URI中沒有埠號。注意該字串在其本身上包含第二個http://。雖然它匹配於第一個組,但不會被搜尋出來,因為整個搜尋表示式不匹配於這部分文字。
再比如下面這個例子,以下程式碼示例使用 Match.Result 來從 URL提取協議和埠號。例如,"http://www.yahoo.com.cn:8080/index.html"將返回"http:8080"。