如何修复这个正则表达式?

Posted

技术标签:

【中文标题】如何修复这个正则表达式?【英文标题】:How can I fix this regex expression? 【发布时间】:2020-05-03 15:42:14 【问题描述】:

前言:这个问题是this question的派生题。


Here is my code:

using System;
using System.Linq;
using System.Text.RegularExpressions;

class MainClass 
  public static void Main (string[] args) 
        const string rawLine = "\"TeamName\",\"PlayerName\",\"Position\"  \"Chargers\",\"Philip Rivers\",\"QB\"  \"Colts\",\"Peyton Manning\",\"QB\"  \"Patriots\",\"Tom Brady\",\"QB\"";
        var parsedLines = Regex.Split(rawLine, "(\".*? \"(?:,\".*? \")*)");
        parsedLines.ToList().ForEach(Console.WriteLine);

        Console.WriteLine("Press [ENTER] to exit.");
        Console.ReadLine();
  

这是我的输出:

"TeamName","PlayerName","Position"  "
Chargers
","Philip Rivers","QB"  "
Colts
","Peyton Manning","QB"  "
Patriots","Tom Brady","QB"
Press [ENTER] to exit.

这是我想要的输出:

"TeamName","PlayerName","Position"
"Chargers","Philip Rivers","QB"
"Colts","Peyton Manning","QB"
"Patriots","Tom Brady","QB"
Press [ENTER] to exit.

如何修复正则表达式以生成我想要的输出?


相关:

line breaks lost in sql server How do you view ALL text from an ntext or nvarchar(max) in SSMS?

【问题讨论】:

我强烈建议您使用 CSVHelper 而不是正则表达式,除非您确定 CSV 不会包含嵌入/转义引号或逗号之类的内容。 CSV 是一种非常灵活的格式。它甚至不必用逗号分隔即可成为 CSV。 @Amy 我不熟悉 CSVHelper,但我很熟悉。能否请您描述一个使用 CSVHelper 的解决方案? 我已经很久没有需要它的服务了(过去几年没有 CSV :o),但我记得他们的文档相当不错。见joshclose.github.io/CsvHelper/getting-started。 或者甚至可以用"\"\n\"" 或任何你想要的换行符替换"\" \"" 除非 CSVHelper 有办法指定 record 分隔符,否则它不会有任何帮助。上一个问题的答案(已删除)提到了 CSVHelper 配置的 Delimiter 属性,但那是 field 分隔符(这就是它被删除的原因)。我找不到记录分隔符选项(但这并不意味着没有)。那里的另一个答案提到了在两个空格和quote-space-space-quote上的拆分,所以人们希望在转向正则表达式然后发布这个问题之前已经探索过。 【参考方案1】:

使用否定的lookbehind、肯定的lookbehind、带量词的字符类、肯定的lookahead 和否定的lookahead。

Working Demo

using System;
using System.Linq;
using System.Text.RegularExpressions;

class MainClass 
  public static void Main (string[] args) 
        const string rawLine = "\"TeamName\",\"PlayerName\",\"Position\"  \"Chargers\",\"Philip Rivers\",\"QB\"  \"Colts\",\"Peyton Manning\",\"QB\"  \"Patriots\",\"Tom Brady\",\"QB\"";
            var parsedLines = Regex.Split(rawLine, "(?<![,])(?<=[\"])[ ]2(?=[\"])(?![,])");
            parsedLines.ToList().ForEach(Console.WriteLine);

            Console.WriteLine("Press [ENTER] to exit.");
            Console.ReadLine();
  

【讨论】:

【参考方案2】:

正如 Amy 已经提到的,您的字符串似乎类似于 CSV。如果它确实是有效的 CSV - 请使用特殊库。

如果 CSVHelper 在这种情况下不适用并且您确实需要正则表达式,请尝试以下操作:

(?<=(?:^|  ))(.*?)(?=(?:  \")|$)

我没有为 C# 编码,因此由于 c# 特定,正则表达式可能需要一些编辑。

编辑。代码示例。

using System;
using System.Linq;
using System.Text.RegularExpressions;

class MainClass 
  public static void Main (string[] args) 
        const string rawLine = "\"TeamName\",\"PlayerName\",\"Position\"  \"Chargers\",\"Philip Rivers\",\"QB\"  \"Colts\",\"Peyton Manning\",\"QB\"  \"Patriots\",\"Tom Brady\",\"QB\"";
            //var parsedLines = Regex.Split(rawLine, "(?<=(?:^|  ))(.*?)(?=(?:  \")|$)");
      var parsedLines = Regex.Split(rawLine, "(?<=^)(.*?)(?=(?:  \")|$)|(?<=  )(.*?)(?=(?:  \")|$)");
            parsedLines.ToList().ForEach(Console.WriteLine);

            Console.WriteLine("Press [ENTER] to exit.");
            Console.ReadLine();
  

此代码带有“脏”修复断言错误。但是,我无法使用 onlinetool 复制它:) 此示例中注释的原始正则表达式。

我希望这会对你有所帮助。但我必须再说一遍,如果你使用 csv - 最好使用特殊工具,而不是正则表达式 :)

【讨论】:

您可以使用 dotnetfiddle 或 regexstorm 在 c# 中测试正则表达式。 哎呀,谢谢。我错过了我可以在您提供的 repl.it 链接上进行测试。正则表达式她似乎很好。但是如果 C# 出现断言错误 - 我们可以尝试“脏”修复。我现在就编辑我的帖子。【参考方案3】:

贯穿整个线程的优秀 cmets(我强烈建议采用其中一种选择),我不会专注于它们。这是一个替代解决方案,它使用Regex 模式中的Matchesskip 你有多少字段(列),然后take 你想要多少记录。

我正在使用(\"(.*?)[^,]") 之类的模式,可以在here 中找到其含义的解释。

const string rawLine = "\"TeamName\",\"PlayerName\",\"Position\"  \"Chargers\",\"Philip Rivers\",\"QB\"  \"Colts\",\"Peyton Manning\",\"QB\"  \"Patriots\",\"Tom Brady\",\"QB\"";                       
var matches = new Regex(@"(\""(.*?)[^,]"")").Matches(rawLine).Cast<Match>().ToList();
// loop through our matches
for(int i = 0; i < matches.Count; i++)
                
    // join our records we need to output
    string str = string.Join(",", matches.Skip(i * 3).Take(3));
    if(!string.IsNullOrEmpty(str))
         Console.WriteLine(str);
            
Console.WriteLine("Press [ENTER] to exit.");
Console.ReadLine();

请注意,根本没有错误检查,可以改进,但会产生您需要的输出。 *还要确保导入System.Linq(如果还没有)。

输出测试

【讨论】:

以上是关于如何修复这个正则表达式?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中修复正则表达式

使用正则表达式映射系列时如何修复 np.cumsum 函数

如何修复 jsx 结束标签上的 linting 错误:“未关闭的正则表达式”?

尝试在 JavaScript 中使用 Gruber 的“改进的”URL 匹配正则表达式模式时,如何修复“无效组”错误?

需要修复我的正则表达式

javascript 正则表达式修复NLP