【问题标题】:C# and Regex: How to extract strings between quotation marksC# 和正则表达式:如何提取引号之间的字符串
【发布时间】:2009-05-22 07:52:23
【问题描述】:

假设我有以下字符串:

var 联赛 = 新数组( "足球","德国 - 2. 德甲","38542195","102","2009 年 5 月 24 日 14:00","2009 年 5 月 24 日 14:00","1X2","1","0" ); var 匹配 = 新数组( "125","1.FC 纽伦堡 - TSV 1860 慕尼黑","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|1.40|4.10|6.40|-","|| ||","1|1.90|3.50|2.20|0:1","1|1.05|2.20|1.18|-","1|2.00||1.60|2.5","1|3.40|3.20|1.60| 2","1|1.70|2.50|5.50|-","||||-","1", "126","FC Ingolstadt 04 - TuS Koblenz","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|3.60|2.80|2.00|-","|||| ","||||:","1|1.68|1.25|1.26|-","1|1.90||1.70|2.5","1|3.10|3.10|1.70|2","1|3.60| 2.10|2.45|-","||||-","1", "127","FC St.Pauli 1910 - FSV 法兰克福","2009 年 5 月 24 日 14:00","周日 24.05.09 14:00","1|2.50|2.95|2.60|-","|| ||","||||:","1|1.41|1.44|1.28|-","1|2.00||1.60|2.5","1|3.40|3.20|1.60|2","1| 2.95|2.00|3.05|-","||||-","1", "128","MSV Duisburg - VfL Osnabruck","2009 年 5 月 24 日 14:00","周日 24.05.09 14:00","1|2.30|3.60|2.40|-","||||" ,"||||:","1|1.35|1.51|1.27|-","1|2.10||1.55|2.5","1|3.60|3.20|1.55|2","||||- ","||||-","1", "129","FSV 美因茨 05 - SC Rot-Weiss Oberhausen","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|1.40|3.80|7.00|-","| |||","1|1.95|3.50|2.50|0:1","1|1.05|2.50|1.18|-","1|2.00||1.60|2.5","1|3.40|3.20|1.60 |2","1|1.70|2.30|5.50|-","||||-","1", "130","Rot-Weiss Ahlen - SpVgg Greuther Furth","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|2.55|3.20|2.55|-","|| ||","||||:","1|1.42|1.42|1.28|-","1|2.10||1.55|2.5","1|3.60|3.20|1.55|2","1| 3.00|2.00|3.00|-","||||-","1", "131","SC Freiburg - 1.FC Kaiserslautern","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|1.75|3.25|4.20|-","||| |","||||:","1|1.17|1.91|1.24|-","1|2.10||1.55|2.5","1|3.60|3.20|1.55|2","1|2.30 |2.10|3.80|-","||||-","1", "132","SV Wehen Wiesbaden - FC Hansa Rostock","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|5.00|3.70|1.55|-","||| |","||||:","1|2.23|1.09|1.23|-","1|1.90||1.70|2.5","1|3.10|3.10|1.70|2","1|4.50 |2.25|2.00|-","||||-","1", "133","TSV Alemannia Aachen - FC Augsburg","2009 年 5 月 24 日 14:00","Sun, 24.05.09 14:00","1|1.60|3.45|5.10|-","|||| ","||||:","1|1.11|2.13|1.23|-","1|2.10||1.55|2.5","1|3.60|3.20|1.55|2","1|2.10| 2.20|4.30|-","||||-","1" ); var events = showLeague(联赛,比赛); hasEvents = hasEvents + 事件; 脚本>

我要做的是解析它读取“var 匹配”的部分并提取两个引号之间包含的任何内容。因此,期望的结果应该是一个包含:

(0): 125 (1): 1.FC 纽伦堡 - TSV 1860 慕尼黑 (2):2009年5月24日14:00 等等。

注意:我看到有人回答了类似的问题,但经过一段时间后,我无法让它发挥作用。谢谢!

【问题讨论】:

标签: c# regex parsing


【解决方案1】:

请不要为此使用正则表达式,CSV 应由解析器处理。使用正则表达式执行此操作是最慢且最容易出错的方法。

这是一个现成的解析器:codeproject.com: A Fast CSV Reader。其他示例很容易找到,因为实现 CSV 解析器是一种流行的练习。

您也可以使用 OLEDB 内置解析器:C# Tutorial - Using The Built In OLEDB CSV Parser

以您的示例为例,我将使用IndexOf() 剪切"var matches = new Array("");" 之间的字符串,并将结果视为CSV 字符串。

【讨论】:

  • 公平地说,我遇到的大多数解析器生成器都使用正则表达式来定义语法。
  • @DrJokepu:用正则表达式解析 CSV 数据并非不可能。但这不是最有效的方法。正则表达式的时间消耗可能是指数 O(n^c)(由于回溯),而解析器只有 O(n)。 (我希望估计是正确的。)
【解决方案2】:

尝试以下方法:

using System.Text.RegularExpressions;

public static MatchCollection getMatches(String input, String pattern) {
   Regex re = new Regex(pattern);
   return re.Matches(input);
}

public static void Example() {
   String pattern1 = "var matches = new Array\\(([^\\)]+)\\)";

   MatchCollection results = getMatches(RandomTest, pattern1);
   String marray = results[0].Groups[1].Value;

   String pattern2 = "\"([^\"]+)\"";
   List<String> values = new List<String>();
   foreach (Match value in getMatches(marray,pattern2)) {
      //Your values are in the Groups property
      values.Add(value.Groups[1].Value);
      Console.WriteLine(value.Groups[1].Value);
   }
}

第一个模式提取匹配数组,第二个模式获取该数组中所有引用的值

【讨论】:

    【解决方案3】:

    我会使用以下正则表达式模式来匹配整个数组内容:

    "var matches = new Array\(\s+(.*?)\s+\)"
    

    ... 然后在逗号分隔符上执行 String.Split。

    【讨论】:

      【解决方案4】:

      我认为您需要删除开头和结尾的 " 并拆分为 ","

      string [] test=Regex.Split(s.SubString(1,s.length-2), "\",\"");
      

      【讨论】:

        【解决方案5】:

        如果你真的想使用正则表达式,试试这样:

        var matches = new Array\(\s*("(?:[^\\"]*|\\.)*"\s*(?:,\s*"(?:[^\\"]*|\\.)*")*)\s*\);
        

        这应该会为您提供数组值列表。然后另一个正则表达式可以为您获取单个值:

        "(?:[^\\"]*|\\.)*"
        

        但同样:在这种情况下使用正则表达式并不是那么有效。一个简单的 CSV 解析器会更好。

        【讨论】:

          【解决方案6】:

          如果您需要将所有行放在一个列表中,请使用:

          /// <returns>Returns all values inside matches array in a single list</returns>
                  public static List<string> GetMatchesArray(String inputString)
                  {
                      // Matches var matches = new Array( ... );
                      Regex r = new Regex("(var matches = new Array\\([^\\)]*\\);)",
                          RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline);
          
                      string arrayString = r.Match(inputString).Groups[0].Value;
          
                      List<string> quotedList = new List<string>();
          
                      // Matches all the data between the quotes inside var matches
                      r = new Regex("\"([^\"]+)\"", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline);
                      for (Match m = r.Match(arrayString); m.Success; m = m.NextMatch())
                      {
                          quotedList.Add(m.Groups[1].Value);
                      }
          
                      return quotedList;
                  }
          

          如果你想每行有一个单独的列表,你应该有一个行列表,并且在每个列表中你应该有一个引用文本的列表。下面的代码将做到这一点:

          /// This will help you store the data in a list in a more meaningful way, 
          /// so that you are able to organize the data per line
          /// Returns all the quoted text per line in a list of lines
          public static List<List<string>> GetMatchesArrayPerLine(String inputString)
          {
              // Matches var matches = new Array( ... )
              Regex r = new Regex("(var matches = new Array\\([^\\)]*\\);)",
                  RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline);
          
              string arrayString = r.Match(inputString).Groups[0].Value;
          
              List<string> lineList = new List<string>();
          
              // Matches all the lines and stores them in lineList one line per item. For e.g.
              // "125","1.FC Nurnberg - TSV 1860 Munich", ...
              // "126","FC Ingolstadt 04 - TuS Koblenz", ...
              r = new Regex("\n(.*)", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline);
              for (Match m = r.Match(arrayString); m.Success; m = m.NextMatch())
              {
                  lineList.Add(m.Groups[1].Value);
              }
          
              List<List<string>> quotedListPerLine = new List<List<string>>();
          
              // Matches the quoted text per line. 
              // This will help you store data in an organised way rather than just a list of values
              // Similar to a 2D array
              // quotedListPerLine[0] = List<string> containing { "125", "1.FC Nurnberg - TSV 1860 Munich", ... }
              // quotedListPerLine[1] = List<string> containing { "126","FC Ingolstadt 04 - TuS Koblenz", ... }
              r = new Regex("\"([^\"]+)\"", RegexOptions.IgnoreCase | RegexOptions.Compiled);
              foreach (string line in lineList)
              {
                  List<string> quotedList = new List<string>();
                  for (Match m = r.Match(line); m.Success; m = m.NextMatch())
                  {
                      quotedList.Add(m.Groups[1].Value);
                  }
                  quotedListPerLine.Add(quotedList);
              }
          
              return quotedListPerLine;
          }
          

          为方便起见调用代码:

          List<List<string>> quotedListLines = MyRegEx.GetMatchesArrayPerLine(a);
          foreach (List<string> line in quotedListLines)
          {
              Console.WriteLine("----LINE---");
              foreach (string quotedText in line)
                  Console.WriteLine(quotedText);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-01-25
            • 2014-11-05
            • 1970-01-01
            • 2017-01-29
            • 2015-05-28
            相关资源
            最近更新 更多