2016-08-01 39 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