解讀 C 中的正規表示式

2021-06-15 21:40:31 字數 4583 閱讀 4782

多少年來,許多的程式語言和工具都包含對正規表示式的支援,.net基礎類庫中包含有乙個名字空間和一系列可以充分發揮規則表示式威力的類,而且它們也都與未來的perl 5中的規則表示式相容。

此外,regexp類還能夠完成一些其他的功能,例如從右至左的結合模式和表示式的編輯等。

在這篇文章中,我將簡要地介紹system.text.regularexpression中的類和方法、一些字串匹配和替換的例子以及組結構的詳細情況,最後,還會介紹一些你可能會用到的常見的表示式。

應該掌握的基礎知識

規則表示式的知識可能是不少程式設計人員「常學常忘」的知識之一。在這篇文章中,我們將假定你已經掌握了規則表示式的用法,尤其是perl 5中表示式的用法。.net的regexp類是perl 5中表示式的乙個超集,因此,從理論上說它將作為乙個很好的起點。我們還假設你具有了c#的語法和.net架構的基本知識。

如果你沒有規則表示式方面的知識,我建議你從perl 5的語法著手開始學習。在規則表示式方面的權威書籍是由傑弗里·弗雷德爾編寫的《掌握表示式》一書,對於希望深刻理解表示式的讀者,我們強烈建議閱讀這本書。

regularexpression組合體

regexp規則類包含在system.text.regularexpressions.dll檔案中,在對應用軟體進行編譯時你必須引用這個檔案,例如:

csc r:system.text.regularexpressions.dll foo.cs

命令將建立foo.exe檔案,它就引用了system.text.regularexpressions檔案。

名字空間簡介

在名字空間中僅僅包含著6個類和乙個定義,它們是:

capture: 包含一次匹配的結果;

capturecollection: capture的序列;

group: 一次組記錄的結果,由capture繼承而來;

match: 一次表示式的匹配結果,由group繼承而來;

matchcollection: match的乙個序列;

matchevaluator: 執行替換操作時使用的**;

regex: 編譯後的表示式的例項。

regex類中還包含一些靜態的方法:

escape: 對字串中的regex中的轉義符進行轉義;

ismatch: 如果表示式在字串中匹配,該方法返回乙個布林值;

match: 返回match的例項;

matches: 返回一系列的match的方法;

replace: 用替換字串替換匹配的表示式;

split: 返回一系列由表示式決定的字串;

unescape:不對字串中的轉義字元轉義。

簡單匹配

我們首先從使用regex、match類的簡單表示式開始學習。

match m = regex.match("abracadabra", "(a|b|r)+");

我們現在有了乙個可以用於測試的match類的例項,例如:if (m.success)...

如果想使用匹配的字串,可以把它轉換成乙個字串:

console.writeline("match="+m.tostring());

這個例子可以得到如下的輸出: match=abra。這就是匹配的字串了。

字串的替換

簡單字串的替換非常直觀。例如下面的語句:

string s = regex.replace("abracadabra", "abra", "zzzz");

它返回字串zzzzcadzzzz,所有匹配的字串都被替換成了zzzzz。

現在我們來看乙個比較複雜的字串替換的例子:

string s = regex.replace(" abra ", @"^/s*(.*?)/s*$", "$1");

這個語句返回字串abra,其前導和字尾的空格都去掉了。

上面的模式對於刪除任意字串中的前導和後續空格都非常有用。在c#中,我們還經常使用字母字串,在乙個字母字串中,編譯程式不把字元「 /」 作為轉義字元處理。在使用字元「/」指定轉義字元時,@"..."是非常有用的。另外值得一提的是$1在字串替換方面的使用,它表明替換字串只能包含被替換的字串。

匹配引擎的細節

現在,我們通過乙個組結構來理解乙個稍微複雜的例子。看下面的例子:

string text = "abracadabra1abracadabra2abracadabra3";

string pat = @"

( # 第乙個組的開始

abra # 匹配字串abra

( # 第二個組的開始

cad # 匹配字串cad

)? # 第二個組結束(可選)

) # 第乙個組結束

+ # 匹配一次或多次

"; //利用x修飾符忽略注釋

regex r = new regex(pat, "x");

//獲得組號碼的清單

int gnums = r.getgroupnumbers();

//首次匹配

match m = r.match(text);

while (m.success) }

//下乙個匹配

m = m.nextmatch(); }

這個例子的輸出如下所示:

group1=[abra]

capture0=[abracad] index=0 length=7

capture1=[abra] index=7 length=4

group2=[cad]

capture0=[cad] index=4 length=3

group1=[abra]

capture0=[abracad] index=12 length=7

capture1=[abra] index=19 length=4

group2=[cad]

capture0=[cad] index=16 length=3

group1=[abra]

capture0=[abracad] index=24 length=7

capture1=[abra] index=31 length=4

group2=[cad]

capture0=[cad] index=28 length=3

我們首先從考查字串pat開始,pat中包含有表示式。第乙個capture是從第乙個圓括號開始的,然後表示式將匹配到乙個abra。第二個capture組從第二個圓括號開始,但第乙個capture組還沒有結束,這意味著第乙個組匹配的結果是abracad ,而第二個組的匹配結果僅僅是cad。因此如果通過使用?符號而使cad成為一項可選的匹配,匹配的結果就可能是abra或abracad。然後,第乙個組就會結束,通過指定+符號要求表示式進行多次匹配。

現在我們來看看匹配過程中發生的情況。首先,通過呼叫regex的constructor方法建立表示式的乙個例項,並在其中指定各種選項。在這個例子中,由於在表示式中有注釋,因此選用了x選項,另外還使用了一些空格。開啟x選項,表示式將會忽略注釋和其中沒有轉義的空格。

然後,取得表示式中定義的組的編號的清單。你當然可以顯性地使用這些編號,在這裡使用的是程式設計的方法。如果使用了命名的組,作為一種建立快速索引的途徑這種方法也十分有效。

接下來是完成第一次匹配。通過乙個迴圈測試當前的匹配是否成功,接下來是從group 1開始重複對組清單執行這一操作。在這個例子中沒有使用group 0的原因是group 0是乙個完全匹配的字串,如果要通過收集全部匹配的字串作為乙個單一的字串,就會用到group 0了。

我們跟蹤每個group中的capturecollection。通常情況下每次匹配、每個group中只能有乙個capture,但本例中的group1則有兩個capture:capture0和capture1。如果你僅需要group1的tostring,就會只得到abra,當然它也會與abracad匹配。組中tostring的值就是其capturecollection中最後乙個capture的值,這正是我們所需要的。如果你希望整個過程在匹配abra後結束,就應該從表示式中刪除+符號,讓regex引擎知道我們只需要對表示式進行匹配。

基於過程和基於表示式方法的比較

一般情況下,使用規則表示式的使用者可以分為以下二大類:第一類使用者盡量不使用規則表示式,而是使用過程來執行一些需要重複的操作;第二類使用者則充分利用規則表示式處理引擎的功能和威力,而盡可能少地使用過程。

對於我們大多數使用者而言,最好的方案莫過於二者兼而用之了。我希望這篇文章能夠說明.net語言中regexp類的作用以及它在效能和複雜性之間的優、劣點。

基於過程的模式

我們在程式設計中經常需要用到的乙個功能是對字串中的一部分進行匹配或其他一些對字串處理,下面是乙個對字串中的單詞進行匹配的例子:

string text = "the quick red fox jumped over the lazy brown dog.";

system.console.writeline("text=[" + text + "]")

全面解讀php 正規表示式

示例 現在需要正則驗證乙個input框,我想輸入的是非整數就自動變成空值。正則如下 不加入 g,則只返回第乙個匹配,無論執行多少次均是如此,如果加入g,則第一次執行也返回第乙個匹配,再執行返回第二個匹配,依次類推。0 9 g,這個正規表示式的意思是全域性匹配非數字型別和非 的字元。0 9 g 匹配到...

C 中的正規表示式

字元 描述 將下乙個字元標記為乙個特殊字元 或乙個原義字元 或乙個 向後引用 或乙個八進位制轉義符。例如,n 匹配字元 n 匹配乙個換行符。序列 匹配 而 則匹配 匹配輸入字串的開始位置。如果設定了 regexp 物件的 multiline 屬性,也匹配 或 之後的位置。匹配輸入字串的結束位置。如果...

C 中的正規表示式

位置匹配符 表示一行文字的開始位置 表示一行文字的結束位置 如 表示式 cat 匹配的單詞cat出現在行的開始處,注意 是乙個位置字元,不是要匹配字元的本身。同樣,表示式 cat 匹配的單詞cat出現來一行的結尾處。方括號 它表示匹配括號中字元中的乙個 例如 我們要查詢文字中,所有包含 gray或者...