簡體   English   中英

使用正則表達式在C#擴展方法中解析字符串

[英]Parse string in C# extension method with regex

我需要創建解析(分割)我的字符串的擴展方法。

例如:如果我有字符串

命令1已處理“作業命令” 20160801 09:05:24

應該這樣分割

命令

1個

處理

“ JOB命令”

20160801

09:05:24

其他例子。 如果我有字符串:

命令2錯誤06 00000032“消息窗口仍處於活動狀態。” 20160801 09:05:24

應該這樣分割:

命令

2

錯誤

06

00000032

“消息窗口仍處於活動狀態。”

20160801 09: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;
        }

我想實施更清潔的解決方案。 有任何想法嗎?

我建議實現一個簡單的循環而不是復雜的正則表達式

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);
}

過了一會兒,想出了一些簡單的代碼:

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

我用一個MessageBox測試了代碼,該MessageBox顯示了帶有|List | 在每個項目之間:

在此處輸入圖片說明

您可以使用帶有(globlal)標識符的正則表達式,如: ([^\\s"]+|"[^"]*")

演示與講解

純正則表達式解決方案:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM