2013-10-25 184 views
5

我有以下字符串:正則表達式嵌套的括號

a,b,c,d.e(f,g,h,i(j,k)),l,m,n 

會知道的告訴我,我怎麼能建立一個只返回我的括號像這樣的「第一級」正則表達式:

[0] = a,b,c, 
[1] = d.e(f,g,h,i.j(k,l)) 
[2] = m,n 

目標是保持嵌套在括號中的具有相同索引的部分來操縱未來。

謝謝。

編輯

試圖改善的例子...

想象我有這個字符串

username,TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2)),password 

我的目標是把一個字符串轉換爲動態查詢。 然後,不以「TB_」開頭的字段我知道它們是主表的字段,否則我知道括號內的informandos字段與另一個表有關。 但我很難檢索所有領域的「第一級」,因爲我可以將它們從相關表中分離出來,我可以遞歸地恢復剩餘的字段。

最終,將有類似:

[0] = username,password 
[1] = TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2)) 

我希望我已經解釋過好一點,不好意思。

+2

我不明白你的例子。 –

+0

不應該匹配'[1]'是'(f,g,h,i.j(k,l))'?如果沒有,請你多解釋一下? – Vache

+1

從我知道,正則表達式無法解析嵌套結構 – Jonesopolis

回答

7

您可以使用此:

(?>\w+\.)?\w+\((?>\((?<DEPTH>)|\)(?<-DEPTH>)|[^()]+)*\)(?(DEPTH)(?!))|\w+ 

你的榜樣,你獲得:

0 => username 
1 => TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2)) 
2 => password 

說明:

(?>\w+\.)? \w+ \( # the opening parenthesis (with the function name) 
(?>     # open an atomic group 
    \( (?<DEPTH>) # when an opening parenthesis is encountered, 
        # then increment the stack named DEPTH 
    |     # OR 
    \) (?<-DEPTH>) # when a closing parenthesis is encountered, 
        # then decrement the stack named DEPTH 
    |     # OR 
    [^()]+   # content that is not parenthesis 
)*     # close the atomic group, repeat zero or more times 
\)     # the closing parenthesis 
(?(DEPTH)(?!))  # conditional: if the stack named DEPTH is not empty 
        # then fail (ie: parenthesis are not balanced) 

你可以用這個代碼試試:

string input = "username,TB_PEOPLE.fields(FirstName,LastName,TB_PHONE.fields(num_phone1, num_phone2)),password"; 
string pattern = @"(?>\w+\.)?\w+\((?>\((?<DEPTH>)|\)(?<-DEPTH>)|[^()]+)*\)(?(DEPTH)(?!))|\w+"; 
MatchCollection matches = Regex.Matches(input, pattern); 
foreach (Match match in matches) 
{ 
    Console.WriteLine(match.Groups[0].Value); 
} 
+0

嗨! 我試圖正確應用正則表達式,但是我得到的回報是這樣的:[0] =>「」[1] =>「,」[2] =>「,」, 3] =>「」 可以告訴我我忘了什麼嗎? 謝謝。 – Verner

+0

@Verner:我添加了一個示例代碼。 –

+0

在原子內部使用嵌套量化組可能會更好,以防止回溯並加速識別失敗的匹配。即'(((?>(?:\((?)| \)(?<-DEPTH>)| [^()] +)*)\)'。但是,如果你不關心失敗的表現,那就沒有必要。 (只有可讀性的空間) – Adrian

0

如果我理解正確你的榜樣,你正在尋找的東西是這樣的:

(?<head>[a-zA-Z._]+\,)*(?<body>[a-zA-Z._]+[(].*[)])(?<tail>.*) 

對於給定的字符串:

用戶名,TB_PEOPLE.fields(名字,姓氏,TB_PHONE.fields( num_phone1,num_phone2)),密碼

此表達式將匹配

  • 用戶名,爲組
  • TB_PEOPLE.fields(名字,姓氏,TB_PHONE.fields(num_phone1,num_phone2))爲組
  • ,密碼爲組
0

我建議一個新的策略,R2 - 做算法。雖然你可以構建一個正則表達式,它最終會接近你所要求的,但是當你發現新的邊緣情況時,這將是非常難以維護的,很難延長。我不說話C#,但是這個僞代碼應該讓你在正確的軌道上:

function parenthetical_depth(some_string): 
    open = count '(' in some_string 
    close = count ')' in some_string 
    return open - close 

function smart_split(some_string): 
    bits = split some_string on ',' 
    new_bits = empty list 
    bit = empty string 
    while bits has next: 
     bit = fetch next from bits 
     while parenthetical_depth(bit) != 0: 
      bit = bit + ',' + fetch next from bits 
     place bit into new_bits 
    return new_bits 

這是瞭解它的最簡單的方法,算法是目前O(n^2) - 有一個爲內環,以使優化它O(n)(與字符串複製之外,這是一種本最糟糕的部分的):

depth = parenthetical_depth(bit) 
while depth != 0: 
    nbit = fetch next from bits 
    depth = depth + parenthetical_depth(nbit) 
    bit = bit + ',' + nbit 

字符串複製可以由具有巧妙地利用緩衝液和緩衝大小的效率更高,在成本的空間效率,但我不認爲C#本身就給你提供了這種控制級別。