2011-09-30 38 views
2

我收集的文本文件:C#正則表達式:如何提取集合

(Collection 
    (Item "Name1" 1 2 3) 
    (Item "Simple name2" 1 2 3) 
    (Item "Just name 3" 4 5 6)) 

集也可能是空的:

(Collection) 

項目的數量是不確定的。它可能是一件或一百件。由以前的提取我已經有集合元素之間的內部文本:

(Item "Name1" 1 2 3)(Item "Simple name2" 1 2 3)(Item "Just name 3" 4 5 6) 

在空集的情況下,這將是空字符串。

如何使用.Net正則表達式解析此集合?

我嘗試這樣做:

string pattern = @"(\(Item\s""(?<Name>.*)""\s(?<Type>.*)\s(?<Length>.*)\s(?<Number>.*))*"; 

但上面的代碼不會產生任何實際效果。

UPDATE:

我試圖用正則表達式是不同的:

foreach (Match match in Regex.Matches(document, pattern, RegexOptions.Singleline)) 
{ 
    for (int i = 0; i < match.Groups["Name"].Captures.Count; i++) 
    { 
     Console.WriteLine(match.Groups["Name"].Captures[i].Value); 
    } 
} 

while (m.Success) 
{ 
    m.Groups["Name"].Value.Dump(); 
    m.NextMatch(); 
} 
+0

你想在輸出什麼? –

+0

@Michele Virgilio:在輸出中,我想提取所有項目,例如名稱,類型,長度和數字 –

+0

所以你只需要解析(Item「Name1」1 2 3)(Item「Simple name2」1 2 3)(Item「Just name 3」4 5 6) 不是整個字符串 –

回答

3

嘗試

\(Item (?<part1>\".*?\")\s(?<part2>\d+)\s(?<part3>\d+)\s(?<part4>\d+)\) 

這將創建一個匹配的集合:

Regex regex = new Regex(
     "\\(Item (?<part1>\\\".*?\\\")\\s(?<part2>\\d+)\\s(?<part3>\\d"+ 
     "+)\\s(?<part4>\\d+)\\)", 
    RegexOptions.Multiline | RegexOptions.Compiled 
    ); 

//Capture all Matches in the InputText 
MatchCollection ms = regex.Matches(InputText); 


//Get the names of all the named and numbered capture groups 
string[] GroupNames = regex.GetGroupNames(); 

// Get the numbers of all the named and numbered capture groups 
int[] GroupNumbers = regex.GetGroupNumbers(); 
+0

中我不知道這是否有效,但始終使用最小捕獲(例如\ d +總是比一個大規模的貪婪的比賽要好,因爲這樣會很高興地匹配你所有的分隔符和其他一半的機會,我甚至希望看到第一個。*被替換成更具體的東西,儘管我們沒有知道當前有效的內容 – Chris

+0

事實上,貪婪的匹配僅用於「可以包含任何文本的分隔符」之間 –

+1

問題是貪婪的匹配將匹配給定一半機會的分隔符,例如當您有兩個項目時它會匹配'Name1'1 2 3)(Item「Simple name2」1 2 3)(Item「Just name 3'。Using [^」] *會比*更好,以防止它與你的分隔符匹配。可能是一些逃脫的機甲nism在報價單內的報價,在這種情況下,這會因其他原因而失敗... – Chris

2

我想你可能需要讓您捕捉非貪婪...

(?<Name>.*?) 

代替

(?<Name>.*) 
+0

在這種情況下,只有第一個項目被捕獲 –

+1

@JohnKZ:你如何使用正則表達式?使它不貪婪的關鍵是讓它只匹配一個項目,而不是假設第一個項目的名稱是'Name1'1 2 3)(項目「Simple name2」1 2 3)(Item「Just name 3'或者其他同樣的東西 – Chris

+0

@Chris:更新的問題 –

2

我想你應該閱讀文件,並比使用Sting.Split功能分割的收集和開始讀它

String s = "(Collection 
       (Item "Name1" 1 2 3) 
       (Item "Simple name2" 1 2 3) 
       (Item "Just name 3" 4 5 6))"; 

    string colection[] = s.Split('('); 
    if(colection.Length>1) 
    { 
     for(i=1;i<colection.Length;i++) 
     { 
      //process string one by one and add (if you need it 
      //from the last item remove) 
     } 
    } 

這將解決問題很容易,沒有需要額外的調節表達負擔。

+0

我同意這一點。我想當你得到你的一串只是項目時,你必須做類似於上面的事情。在那個階段,我只是解析每個項目,而不是將它放入正則表達式的字符串中。如果沒有其他東西在一個更小的字符串上重新編排,那麼生活會變得更加容易:) – Chris

+0

如果他在其中一個字符串中有括號,這將會失敗。 –

+0

@Ilia Jerebtsov - 根據op給出的刺痛生成代碼..我同意如果有錯誤(出現在字符串 –