2016-08-01 41 views
0

我需要創建一個擴展方法來對我的字符串進行分析(分割)。用正則表達式解析C#擴展方法中的字符串

例如: 如果我有字符串

COMMAND 1處理過的 「JOB命令」 20160801 9時05分24秒

應當分裂這樣

COMMAND

PROCESSED

「JOB命令」

9時05分24秒

其它示例。 如果我有字符串:

命令2錯誤06 00000032「消息窗口仍處於活動狀態。」 20160801 9時05分24秒

應當分裂像這樣:

COMMAND

ERROR

「消息窗口仍處於活動狀態。」

20160801 9時05分24秒

我對這個解決方案。但我相信有更清潔的解決方案。

我的解決辦法:

public static List<string> GetTokens(this string line) 
     { 
      // TODO: Code refactoring: 
      var res = new List<string>(); 
      var parts = Regex.Split(line, "/[^\\s\"']+|\"([^\"]*)\"|'([^']*)'/g"); 

      var subParts = parts[0].Split(' '); 
      foreach (var val in subParts) 
      { 
       res.Add(val); 
      } 
      res.Add(parts[1]); 
      subParts = parts[2].Split(' '); 
      foreach (var val in subParts) 
      { 
       res.Add(val); 
      } 

      res.RemoveAll(f => f.Trim() == ""); 
      return res; 
     } 

我想實現清晰的解決方案。有任何想法嗎?

+2

清潔或工作?這 - '「/ [^ \\ s \」'] + | \「([^ \」] *)\「|'([^'] *)'/ g」' - 顯然不起作用。所以,你的輸入沒有轉義序列,有嗎? –

回答

1

一個而計算出後一些簡單的代碼:

public static List<string> GetTokens(this string line) 
{ 
    return Regex.Matches(line, @"([^\s""]+|""([^""]*)"")").OfType<Match>().Select(l => l.Groups[1].Value).ToList(); 
} 

我測試用MessageBox的代碼,其與|在其之間的每個項目顯示List

enter image description here

4

我建議實施簡易循環而不是複雜正則表達式

public static IEnumerable<String> GetTokens(this string value) { 
    if (string.IsNullOrEmpty(value)) 
    yield break; // or throw exception in case of value == null 

    bool inQuotation = false; 
    int index = 0; 

    for (int i = 0; i < value.Length; ++i) { 
    char ch = value[i]; 

    if (ch == '"') 
     inQuotation = !inQuotation; 
    else if ((ch == ' ') && (!inQuotation)) { 
     yield return value.Substring(index, i - index); 

     index = i + 1; 
    } 
    } 

    if (index < value.Length) 
    yield return value.Substring(index, value.Length - index); 
} 

測試

var source = 
    "COMMAND 2 ERROR 06 00000032 \"Message window is still active.\" 20160801 09:05:24"; 

Console.Write(string.Join(Environment.NewLine, GetTokens(source))); 

輸出

COMMAND 
2 
ERROR 
06 
00000032 
"Message window is still active." 
20160801 
09:05:24 

編輯:如果你想兩個引號類型的"(雙)以及'(單):

public static IEnumerable<String> GetTokens(string value) { 
    if (string.IsNullOrEmpty(value)) 
    yield break; 

    bool inQuotation = false; 
    bool inApostroph = false; 

    int index = 0; 

    for (int i = 0; i < value.Length; ++i) { 
    char ch = value[i]; 

    if (inQuotation) 
     inQuotation = ch != '"'; 
    else if (inApostroph) 
     inApostroph = ch != '\''; 
    else if (ch == '"') 
     inQuotation = true; 
    else if (ch == '\'') 
     inApostroph = true; 
    else if ((ch == ' ') && (!inQuotation)) { 
     yield return value.Substring(index, i - index); 

     index = i + 1; 
    } 
    } 

    if (index < value.Length) 
    yield return value.Substring(index, value.Length - index); 
} 
+0

它看起來像你不處理單引號文字。 –

+0

@WiktorStribiżew:謝謝!由於所提供的示例只使用'「(雙)引號,因此我只實現了對它們的支持;然而,解決方法嘗試(通過正則表達式)提到了'''我已經編輯了答案, '和'''需要 –

+0

是的,現在,它似乎工作得很好(http://ideone.com/UC5iSm)。 –

0

純的正則表達式的解決方案:

public static List<string> GetTokens(this string line) 
{ 
    return Regex.Matches(line, 
     @""".*?""|\S+").Cast<Match>().Select(m => m.Value).ToList(); 
} 

".*?"|\S+正則表達式或者引用字符串或一個非空格字符序列相匹配。然後這些比賽可以一次返回作爲收集。

這裏是一個演示:https://ideone.com/hmLQIt