Visual User
Visual User

Reputation: 69

Parsing command line args with quotes

Ok, so I'm spitting command line arguments by spaces, like Command Prompt, but the problem is, if the user tries to type in DoStuff "argument that has spaces but is quoted" it will not split it correctly. I am using a console application. I've tried to do it like this: baseCommand is the string that the user types in unparsed, and secondCommand is supposed to be the second argument.

int firstQuoteIndex = baseCommand.IndexOf('"');

if (firstQuoteIndex != -1)
{
    int secondQuoteIndex = baseCommand.LastIndexOf('"');
    secondCommand = baseCommand.Substring(firstQuoteIndex, 
        secondQuoteIndex - firstQuoteIndex + 1).Replace("\"", "");
}

This works well, but first, it's messy, and second, I'm not sure how to do this if the user types in something like this:

DoSomething "second arg that has spaces" "third arg that has spaces"

Keep in mind that the user doesn't have to type in quotes if the arg(s) don't have quotes. Does anybody have any suggestions, Thanks.

Upvotes: 2

Views: 2583

Answers (2)

Anu Viswan
Anu Viswan

Reputation: 18155

You could use following Regex for the purpose.

[\""].+?[\""]|[^ ]+

For example,

var commandList = Regex.Matches(baseCommand, @"[\""].+?[\""]|[^ ]+")
                .Cast<Match>()
                .Select(x => x.Value.Trim('"'))
                .ToList();

Sample 1 Input

DoSomething "second arg that has spaces" thirdArgumentWithoutSpaces

Output

Command List
------------
DoSomething 
second arg that has spaces
thirdArgumentWithoutSpaces

Sample 2 Input

DoSomething "second arg that has spaces" "third Argument With Spaces"

Output

Command List
------------
DoSomething 
second arg that has spaces
third Argument With Spaces

Upvotes: 9

Rufus L
Rufus L

Reputation: 37020

I'm sure there's a more elegant way to do this, but one way is to simply walk through your command line one character at a time, keeping track if you're "inside a quoted string", and simply build the arguments as you go, adding them to a list when you encounter an end-quote or a space that's not inside a quoted string.

For example:

public static List<string> ParseCommandLine(string cmdLine)
{
    var args = new List<string>();
    if (string.IsNullOrWhiteSpace(cmdLine)) return args;

    var currentArg = new StringBuilder();
    bool inQuotedArg = false;

    for (int i = 0; i < cmdLine.Length; i++)
    {
        if (cmdLine[i] == '"')
        {
            if (inQuotedArg)
            {
                args.Add(currentArg.ToString());
                currentArg = new StringBuilder();
                inQuotedArg = false;
            }
            else
            {
                inQuotedArg = true;
            }
        }
        else if (cmdLine[i] == ' ')
        {
            if (inQuotedArg)
            {
                currentArg.Append(cmdLine[i]);
            }
            else if (currentArg.Length > 0)
            {
                args.Add(currentArg.ToString());
                currentArg = new StringBuilder();
            }
        }
        else
        {
            currentArg.Append(cmdLine[i]);
        }
    }

    if (currentArg.Length > 0) args.Add(currentArg.ToString());

    return args;
}

Usage might look like:

public static void Main()
{
    var args = "one two \"three four\" five \"six seven\" eight \"nine ten";

    Console.WriteLine($"Command line: \"{args}\"\n");
    Console.WriteLine("Individual Arguments");
    Console.WriteLine("--------------------");
    Console.WriteLine(string.Join(Environment.NewLine, ParseCommandLine(args)));

    GetKeyFromUser("\nDone! Press any key to exit...");
}

Output

enter image description here

Upvotes: 3

Related Questions