2012-05-16 72 views
1

的匹配的第n量表達將總是等於()的數量),但(S)之間可能有任意數量的開合括號對。在這種情況下,我想提取(A(B(D xyz))(C m))。在一個文件中可能有任意數量的(S)子句,所以我不能簡單地做一個^(S。*)$類型的模式匹配。經常用於我需要解析以下形式的表達式括號

如果我知道(S)之間潛在的開啓和閉合括號對的數量,這並不難,但我不知道如何編寫一個正則表達式來知道匹配任意數量的()。

獲得正規表達式任何幫助將不勝感激。提前致謝。

回答

1

這不能在理論上可以做到,而且可以在只有當嵌套的括號的最大數量是已知的前期實踐來完成。這個解決方案需要一個相當不愉快的表達方式,並且通常被嘗試作爲一種奇怪的家庭作業練習。這裏有一個link更好的解釋了爲什麼正則表達式語言不足以解決匹配的括號問題。

你需要一個解析器來解決這個問題;一個簡單的recursive descent人會做的伎倆。上面鏈接中的維基百科文章在C中有一個示例實現,您應該能夠相對容易地將其轉換爲其他語言。

+0

「即使在理論上」 - >我想這應該僅僅是 「理論上」。實用的正則表達式比理論正則表達式更強大;例如a?ba?不能被有限自動機識別,但是一些正則表達式實現將它與(a *)b \ 1或某些匹配。 –

+0

@PascalCuoq你是對的,我刪除了「偶數」部分,並提到當最大數量的嵌套已知時,有解決方案。謝謝! – dasblinkenlight

0

純正則表達式不可能匹配任意數字。換句話說,當你生成/寫入正則表達式是不可能的時候,你無法匹配它未知的計數。只要您在生成正則表達式時知道n,就可以匹配n對(然而高n是)。

0

可能是一個記錄下降解析將是最好的選擇。但是,如果你只是想找到(S)平衡,可以用引擎中的遞歸正則表達式來完成。

它會找到最外面的平衡。如果您正在尋找像(S(S))那樣的嵌套,可能會涉及遞歸調用實現正則表達式的函數,傳遞成功匹配的「核心」。並可能在這個過程中創建一個親子結構。但如果涉及到這一點,一個真正的解析器可能是解決方案。

如何將其與一個Perl的正則表達式來解決 -

$str = '(some (stuff (S (A (B (D xyz)) (C m))) the end) (S extra))'; 

$regex = qr~ 
[(] 
\s* S \s* 
(     # 1 
    (      # 2 
     [(] 
     (?: (?> [^()]+) 
     | (?2)           
    )*            
     [)] 
    ) 
| 
    [^)]* 
) 
[)] 
~x; 

while ($str =~ /$regex/g) 
{ 
    print "found '$1'\n"; 
} 

打印

found '(A (B (D xyz)) (C m))' 
found 'extra'