web-dev-qa-db-fra.com

C # Regex Split - virgules en dehors des guillemets

J'ai pas mal de chaînes (des segments de code SQL, en fait) au format suivant:

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

et j’ai besoin de scinder cette chaîne avec C # pour obtenir:

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

J'utilisais à l'origine un simple Split(','), mais comme cette virgule à l'intérieur du dernier paramètre provoque des dégâts dans la sortie, je dois utiliser Regex pour l'obtenir. Le problème est que je suis encore assez noobish dans les expressions régulières et que je n'arrive pas à craquer le motif principalement parce qu'à l'intérieur de cette chaîne, des paramètres numériques et alphanumériques peuvent exister à tout moment ...

Que pourrais-je utiliser pour scinder cette chaîne en fonction de chaque virgule en dehors des guillemets?

35
João Pereira

Vous pouvez séparer toutes les virgules, suivies d'un nombre pair de guillemets, en utilisant la regex suivante pour les trouver:

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

Vous l'utiliseriez comme

var result = Regex.Split(samplestring, ",(?=(?:[^']*'[^']*')*[^']*$)");
68
Jens
//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);
9
user2661454

bien que moi aussi, j’aime trop un défi de temps en temps, mais ce n’est en fait pas un ., veuillez lire cet article http://secretgeek.net/csv_trouble.asp puis continuez et utilisez http://www.filehelpers.com/

[Edit1, 3]: Ou peut-être que cet article peut aussi vous aider (le lien ne montre que quelques exemples de code VB.Net mais vous pouvez quand même l'utiliser avec C #!): http: // msdn.Microsoft.com/en-us/library/cakac7e6.aspx

J'ai essayé de faire l'exemple pour C # (ajoutez une référence à Microsoft.VisualBasic à votre projet)

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]: En a trouvé un autre qui pourrait être utile ici: http://www.codeproject.com/KB/database/CsvReader.aspx

- Reinhard

6
pastacool

... ou vous auriez pu installer le paquet LumenWorks CsvReader de NuGet et faire quelque chose comme ci-dessous où j'ai lu un fichier csv qui contient un contenu comme par exemple

"hello","how","hello, how are you"
"hi","hello","greetings"
...

et le traiter comme ça

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