代码之家  ›  专栏  ›  技术社区  ›  Registered User

用正则表达式解析退化csv文件中的逗号和引号

  •  1
  • Registered User  · 技术社区  · 16 年前

    我需要解析字符串输入,其中列由列分隔,数据中包含逗号的任何字段都用引号括起来(逗号分隔,带引号的文本标识符)。对于这个项目,我需要删除引号和引号对之间出现的任何逗号。基本上,我需要删除字段中包含的逗号和引号,同时保留用于分隔字段的逗号。下面是我整理的处理简单场景的代码:

    // Sample input 1: This works and covers 99% of the records that I need to parse.
    string str1 = "an_email_address@somewhere.com,2010/03/27 12:2:02,,some_first_name,some_last_name,,\"This Address Works, Suite 200\",Some City,TN,09876-5432,9795551212x123,XYZ";
    str1 = Regex.Replace(str1, "\"([^\"^,]*),([^\"^,]*)\"", "$1$2");
    Console.WriteLine(str1);
    // Outputs: an_email_address@somewhere.com,2010/03/27 12:2:02,,some_first_name,some_last_name,,This Address Works Suite 200,Some City,TN,09876-5432,9795551212x123,XYZ
    

    虽然这段代码适用于我的大多数记录,但当一个字段包含多个逗号时,它不起作用。我要做的是修改代码,以便它删除列中包含的逗号的每个实例,不管字段中有多少个逗号。我不想硬编码只处理2个逗号、3个逗号或25个逗号。代码应该只删除字段中的所有逗号。下面是我的代码处理不当的一个例子。

    // Sample input 2: This doesn't work since there is more than 1 comma between the quotes.
    string str2 = "an_email_address@somewhere.com,2010/03/27 12:2:02,,some_first_name,some_last_name,,\"i,l,k,e, c,o,m,m,a,s, i,n ,m,y, f,i,e,l,d\",Some City,TN,09876-5432,9795551212x123,XYZ";
    str2 = Regex.Replace(str2, "\"([^\"^,]*),([^\"^,]*)\"", "$1$2");
    Console.WriteLine(str2);
    // Desired output: an_email_address@somewhere.com,2010/03/27 12:2:02,,some_first_name,some_last_name,,i like commas in my field,Some City,TN,09876-5432,9795551212x123,XYZ
    

    如何用正则表达式来完成这一点?

    2 回复  |  直到 13 年前
        1
  •  3
  •   Kobi    16 年前

    匹配引号和正则表达式并不能同时进行,正如MichaelMadsen建议的那样,您最好使用csv解析器。
    但是,如果您知道引号仅按预期发生,则可以执行以下操作:

    str2 = Regex.Replace(str2, "\"[^\"]*\"",
                         match => match.Value.Trim('\"').Replace(",", ""));
    
        2
  •  2
  •   Alan Moore Chris Ballance    16 年前

    以下是纯regex版本:

    str2 = Regex.Replace(str0, 
              @"""|,(?=(?>[^""]*""[^""]*(?:""[^""]*""[^""]*)*)$)", 
              String.Empty);
    

    它匹配任何引号或逗号(如果后面跟着奇数个引号),并将其替换为空。

    我只有在必须这样做的情况下才会这样做,例如,如果我使用的框架只允许我指定regex和替换字符串。否则,我要么使用@kobi的方法(因为它可读性更强),要么使用专用的csv处理器。它们并不难找到。