C#Regex Split - 引号外的逗号

时间:2010-06-30 09:08:12

标签: c# regex

我有很多字符串(实际上是SQL代码段),格式如下:

('ABCDEFG', 123542, 'XYZ 99,9')

我需要使用C#拆分此字符串,以获得:

  • 'ABCDEFG'
  • 123542
  • 'XYZ 99,9'

我最初使用的是一个简单的Split(','),但由于最后一个参数中的逗号在输出中造成了破坏,我需要使用Regex来获取它。问题是我在正则表达式中仍然相当无趣,我似乎无法破解模式主要是因为在该字符串内部,数字和字母数字参数可能随时存在......

根据引号之外的每个逗号,我可以使用什么来分割该字符串? 干杯

7 个答案:

答案 0 :(得分:68)

你可以拆分所有逗号,它们后面都有偶数引号,使用以下Regex来查找它们:

",(?=(?:[^']*'[^']*')*[^']*$)"

你会像

一样使用它
var result = Regex.Split(samplestring, ",(?=(?:[^']*'[^']*')*[^']*$)");

答案 1 :(得分:11)

//this regular expression splits string on the separator character NOT inside double quotes. 
//separatorChar can be any character like comma or semicolon etc. 
//it also allows single quotes inside the string value: e.g. "Mike's Kitchen","Jane's Room"
Regex regx = new Regex(separatorChar + "(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"); 
string[] line = regx.Split(string to split);

答案 2 :(得分:6)

虽然我有时候也喜欢挑战,但这实际上不是一个。 请阅读这篇文章http://secretgeek.net/csv_trouble.asp 然后继续使用http://www.filehelpers.com/

[编辑1,3]: 或者这篇文章也可以提供帮助(该链接仅显示一些VB.Net示例代码,但仍然可以将它与C#一起使用!):http://msdn.microsoft.com/en-us/library/cakac7e6.aspx

我尝试为C#做示例(将Microsoft.VisualBasic的引用添加到您的项目中)

using System;
using System.IO;
using Microsoft.VisualBasic.FileIO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            TextReader reader = new StringReader("('ABCDEFG', 123542, 'XYZ 99,9')");
            TextFieldParser fieldParser = new TextFieldParser(reader);

            fieldParser.TextFieldType = Microsoft.VisualBasic.FileIO.FieldType.Delimited;
            fieldParser.SetDelimiters(",");

            String[] currentRow; 

            while (!fieldParser.EndOfData)
            {
                try
                {
                     currentRow = fieldParser.ReadFields();

                     foreach(String currentField in currentRow)
                     {
                        Console.WriteLine(currentField);                        
                     }
                }
                catch (MalformedLineException e)
                {
                    Console.WriteLine("Line {0} is not valid and will be skipped.", e);
               }

            } 

        }
    }
}

<强> [EDIT2]: 找到另一个可能有帮助的地方:http://www.codeproject.com/KB/database/CsvReader.aspx

- reinhard

答案 3 :(得分:4)

我遇到了无法捕获空列的问题。我这样修改它以获得空字符串结果

var results = Regex.Split(source, "[,]{1}(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))");

答案 4 :(得分:0)

在分割方法中尝试(从Jens'攻击):

",(?:.*?'[^']*?')"

或者只是在Jens'*之后添加问号,这使得它变得懒惰而不是贪婪。

答案 5 :(得分:0)

...或者你可以安装NuGet软件包LumenWorks CsvReader并做了类似下面的内容,我读了一个csv文件,里面有例如

的内容
"hello","how","hello, how are you"
"hi","hello","greetings"
...

并像这样处理

public static void ProcessCsv()
        {
            var filename = @"your_file_path\filename.csv";
            DataTable dt = new DataTable("MyTable");

            List<string> product_codes = new List<string>();
            using (CsvReader csv = new CsvReader(new StreamReader(filename), true))
            {
                int fieldCount = csv.FieldCount;

                string[] headers = csv.GetFieldHeaders();
                for (int i = 0; i < headers.Length; i++)
                {
                     dt.Columns.Add(headers[i], typeof(string));
                }

                while (csv.ReadNextRecord())
                {
                    DataRow dr = dt.NewRow();
                    for (int i = 0; i < fieldCount; i++)
                    {
                        product_codes.Add(csv[i]);
                        dr[i] = csv[i];
                    }
                    dt.Rows.Add(dr);
                }
            }
        }

答案 6 :(得分:-1)

已接受的答案对我不起作用(可以在Regexr-dot-com上进行测试并看到它不起作用)。因此,我不得不将这些行读入一系列行中。使用(C#)Regex.Matches获取在转义引号之间找到的所有字符串的数组(您的现场逗号应在用引号引起来的字段中),并将逗号替换为||。在将每一行拆分为列/字段之前。分割每一行后,我循环遍历每一行和每一列以替换||。加上逗号。

        private static IEnumerable<string[]> ReadCsv(string fileName, char delimiter = ';')
    {
        string[] lines = File.ReadAllLines(fileName, Encoding.ASCII);
        // Before splitting on comma for a field array, we have to replace commas witin the fields
        for(int l = 1; l < lines.Length; l++)
        {
            //(\\")(.*?)(\\")
            MatchCollection regexGroup2 = Regex.Matches(lines[l], "(\\\")(.*?)(\\\")");
            if (regexGroup2.Count > 0)
            {
                for (int g = 0; g < regexGroup2.Count; g++)
                {
                    lines[l] = lines[l].Replace(regexGroup2[g].Value, regexGroup2[g].Value.Replace(",", "||"));
                }
            }
        }

        // Split
        IEnumerable<string[]> lines_split = lines.Select(a => a.Split(delimiter));

        // Reapply commas
        foreach(string[] row in lines_split)
        {
            for(int c = 0; c < row.Length; c++)
            {
                row[c] = row[c].Replace("||", ",");
            }
        }

        return (lines_split);
    }