3

Basically, my task is to parse this command line:

-p "This is a string ""with quotes""" d:\1.txt "d:\some folder\1.out"

What I need is to split this string into:

  1. -p
  2. This is a string "with quotes"
  3. d:\1.txt
  4. d:\some folder\1.out

I searched (yes, I really did), but all examples I found either had not included escaped quotes or used \" for escape symbol.

Mogsdad
  • 44,709
  • 21
  • 151
  • 275
cicatrix
  • 163
  • 1
  • 10

3 Answers3

5

I would use a real csv-parser instead, for example the only one available in .NET:

string str = "-p \"This is a string \"\"with quotes\"\"\" d:\\1.txt \"d:\\some folder\\1.out\"";
var allLineFields = new List<string[]>();
using (var parser = new Microsoft.VisualBasic.FileIO.TextFieldParser(new StringReader(str)))
{
    parser.Delimiters = new string[] { " " };
    parser.HasFieldsEnclosedInQuotes = true; // <--- !!!
    string[] lineFields;
    while ((lineFields = parser.ReadFields()) != null)
    {
        allLineFields.Add(lineFields);
    }
}

With your sample string the list contains a single string[] with your four tokens:

-p
This is a string "with quotes"
d:\1.txt
d:\some folder\1.out
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Is there any way I can get by without Microsoft.VisualBasic? – cicatrix Nov 30 '15 at 15:12
  • 1
    [Here](http://stackoverflow.com/questions/2081418/parsing-csv-files-in-c-sharp) you will find alternatives like [this](http://www.codeproject.com/Articles/9258/A-Fast-CSV-Reader) or [this](http://www.filehelpers.net/). But they are not better than the .NET parser – Tim Schmelter Nov 30 '15 at 15:15
1

Using a regex (if you insist on not using a parser as Tim Schmelter's answer suggested), something like this should work (it matches the given string, but I can't guarantee it's completely bullet-proof):

((?:"(?:[^"]|"")*")|\S+)

Breaking it down, you are grouping either:

  • A quote " followed by not a quote ^" or two quotes "", followed by a quote "
  • A bunch (one or more) of non-space characters \S

See here to play around with it.

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

A handwritten version:

private static string[] ParseArguments(string text)
{
    if (string.IsNullOrWhiteSpace(text)) return new string[0];
    var entries = new List<string>(8);
    var stringBuilder = new StringBuilder(64);
    var inString  = false;
    var l = text.Length;
    for (var i = 0; i < l; i++)
    {
        var c = text[i];
        if (inString)
        {
            if (c == '"')
            {
                if (i != l - 1 && text[i + 1] == '"')
                {
                    stringBuilder.Append(c);
                    i++;
                }
                else inString = false;
            }
            else stringBuilder.Append(c);
        }
        else if (c == '"') inString = true;
        else if (char.IsWhiteSpace(c))
        {
            if (stringBuilder.Length == 0) continue;
            entries.Add(stringBuilder.ToString());
            stringBuilder.Length = 0;
        }
        else stringBuilder.Append(c);
    }
    if (stringBuilder.Length != 0) entries.Add(stringBuilder.ToString());
    return entries.ToArray();
}
a-ctor
  • 3,568
  • 27
  • 41