.net c# Regex 平衡組/遞迴匹配

來源:互聯網
上載者:User
.net c# Regex 平衡組/遞迴匹配

平衡組/遞迴匹配

這裡介紹的平衡組文法是由.Net Framework支援的;其它語言/庫不一定支援這種功能,或者支援此功能但需要使用不同的文法。

有時我們需要匹配像( 100 * ( 50 + 15 ) )這樣的可嵌套的層次性結構,這時簡單地使用\(.+\)則只會匹配到最左邊的左括弧和最右邊的右括弧之間的內容(這裡我們討論的是貪婪模式,懶惰模式也有下面的問題)。假如原來的字串裡的左括弧和右括弧出現的次數不相等,比如( 5 / ( 3 + 2 ) ) ),那我們的匹配結果裡兩者的個數也不會相等。有沒有辦法在這樣的字串裡匹配到最長的,配對的括弧之間的內容呢?

為了避免(和\(把你的大腦徹底搞糊塗,我們還是用角括弧代替圓括弧吧。現在我們的問題變成了如何把xx <aa <bbb> <bbb> aa> yy這樣的字串裡,最長的配對的角括弧內的內容捕獲出來?

這裡需要用到以下的文法構造:

(?'group') 把捕獲的內容命名為group,並壓入堆棧(Stack)
(?'-group') 從堆棧上彈出最後壓入堆棧的名為group的捕獲內容,如果堆棧本來為空白,則本分組的匹配失敗
(?(group)yes|no) 如果堆棧上存在以名為group的捕獲內容的話,繼續匹配yes部分的運算式,否則繼續匹配no部分
(?!) 零寬負向先行斷言,由於沒有尾碼運算式,試圖匹配總是失敗
如果你不是一個程式員(或者你自稱程式員但是不知道堆棧是什麼東西),你就這樣理解上面的三種文法吧:第一個就 是在黑板上寫一個"group",第二個就是從黑板上擦掉一個"group",第三個就是看黑板上寫的還有沒有"group",如果有就繼續匹配yes部 分,否則就匹配no部分。

我們需要做的是每碰到了左括弧,就在壓入一個"Open",每碰到一個右括弧,就彈出一個,到了最後就看看堆棧是否為空白--如果不為空白那就證明左括弧比右括弧多,那匹配就應該失敗。Regex引擎會進行回溯(放棄最前面或最後面的一些字元),盡量使整個運算式得到匹配。



複製代碼
< #最外層的左括弧
[^<>]* #最外層的左括弧後面的不是括弧的內容
(
(
(?'Open'<) #碰到了左括弧,在黑板上寫一個"Open"
[^<>]* #匹配左括弧後面的不是括弧的內容
)+
(
(?'-Open'>) #碰到了右括弧,擦掉一個"Open"
[^<>]* #匹配右括弧後面不是括弧的內容
)+
)*
(?(Open)(?!)) #在遇到最外層的右括弧前面,判斷黑板上還有沒有沒擦掉的"Open";如果還有,則匹配失敗

> #最外層的右括弧
複製代碼


平衡組的一個最常見的應用就是匹配HTML,下面這個例子可以匹配嵌套的<div>標籤:



<div[^>]*>[^<>]*(((?'Open'<div[^>]*>)[^<>]*)+((?'-Open'</div>)[^<>]*)+)*(?(Open)(?!))</div>
  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.