2013-12-20 136 views
2

如何使用帶逗號的逗號分隔逗號分隔的字符串?C#拆分逗號分隔值

示例輸入

John, Doe, "Sid, Nency", Smith 

預期輸出

  • 約翰
  • Doe的
  • 西特,Nency
  • 史密斯

以逗號分割是可以的,但我要求允許字符串「Sid,Nency」。我試圖用正則表達式來分割這些值。正則表達式",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"來自Java的問題,它不適合我的.NET代碼。它加倍了一些字符串,發現額外的結果等。

那麼什麼是拆分這種字符串的最佳方式?

+0

它看起來像你處理CSV輸入?如果是這樣,*請*使用CSV庫 - 有很多好的,它會爲您節省很多的痛苦!如果您不是,請澄清您的問題,以解釋爲什麼CSV庫不適合... –

+0

不,它不是一個CSV文檔。這只是一個字符串 – Andrei

+0

RB,如果你給我看,我會很高興,我怎麼能用Csv Lib來處理這個問題 – Andrei

回答

4

這是因爲捕獲組。只要把它變成一個非捕獲組:

",(?=(?:[^""]*""[^""]*"")*[^""]*$)" 
     ^^ 

捕獲組包括捕獲的部分在你的結果。

ideone demo

var regexObj = new Regex(@",(?=(?:[^""]*""[^""]*"")*[^""]*$)"); 
regexObj.Split(input).Select(s => s.Trim('\"', ' ')).ForEach(Console.WriteLine); 

而剛剛修剪的結果。

+0

謝謝!這只是作品! – Andrei

1

只要通過你的字符串。如果您處於「阻止」狀態,則在您穿過字符串時請保持軌跡
。如果你是 - 不要將逗號作爲
逗號(作爲分隔符)。否則,請像這樣對待它。這是一個簡單的
算法,我會自己寫。當你遇到第一個「你輸入
一個塊。當你遇到下一個」,你結束了你的那個塊,等等。
所以你可以通過你的字符串一次。

import java.util.ArrayList; 


public class Test003 { 

    public static void main(String[] args) { 
     String s = " John, , , , \" Barry, John \" , , , , , Doe, \"Sid , Nency\", Smith "; 

     StringBuilder term = new StringBuilder(); 
     boolean inQuote = false; 
     boolean inTerm = false; 
     ArrayList<String> terms = new ArrayList<String>(); 
     for (int i=0; i<s.length(); i++){ 
      char ch = s.charAt(i); 
      if (ch == ' '){ 
       if (inQuote){ 
        if (!inTerm) { 
         inTerm = true; 
        } 
        term.append(ch); 
       } 
       else { 
        if (inTerm){ 
         terms.add(term.toString()); 
         term.setLength(0); 
         inTerm = false; 
        } 
       } 
      }else if (ch== '"'){ 
       term.append(ch); // comment this out if you don't need it 
       if (!inTerm){ 
        inTerm = true; 
       } 
       inQuote = !inQuote; 
      }else if (ch == ','){ 
       if (inQuote){ 
        if (!inTerm){ 
         inTerm = true; 
        } 
        term.append(ch); 
       }else{ 
        if (inTerm){ 
         terms.add(term.toString()); 
         term.setLength(0); 
         inTerm = false; 
        } 
       } 
      }else{ 
       if (!inTerm){ 
        inTerm = true; 
       } 
       term.append(ch); 
      } 
     } 

     if (inTerm){ 
      terms.add(term.toString()); 
     } 

     for (String t : terms){ 
      System.out.println("|" + t + "|"); 
     } 

    } 



} 
+0

以及這是一個想法 – Andrei

+0

@AndreiMikhalevich好的,我只是舉例說明了一些代碼。 –

0

我用下面的代碼我的CSV分析器類中實現這一點:

private string[] ParseLine(string line) 
    { 
     List<string> results = new List<string>(); 
     bool inQuotes = false; 
     int index = 0; 
     StringBuilder currentValue = new StringBuilder(line.Length); 
     while (index < line.Length) 
     { 
      char c = line[index]; 
      switch (c) 
      { 
       case '\"': 
        { 
         inQuotes = !inQuotes; 
         break; 
        } 

       default: 
        { 
         if (c == ',' && !inQuotes) 
         { 
          results.Add(currentValue.ToString()); 
          currentValue.Clear(); 
         } 
         else 
          currentValue.Append(c); 
         break; 
        } 
      } 
      ++index; 
     } 

     results.Add(currentValue.ToString()); 
     return results.ToArray(); 
    } // eo ParseLine 
0

如果你發現正則表達式太複雜,你可以做這樣的:

string initialString = "John, Doe, \"Sid, Nency\", Smith"; 

IEnumerable<string> splitted = initialString.Split('"'); 
splitted = splitted.SelectMany((str, index) => index % 2 == 0 ? str.Split(',') : new[] { str }); 
splitted = splitted.Where(str => !string.IsNullOrWhiteSpace(str)).Select(str => str.Trim());