1

I'm trying to create an interactive shell from an existing application that interprets command line arguments like this:

application.exe command subcommand someNumber=1 boolArgument s="string argument with spaces"

When entering the Main, I receive an string array that contains all the arguments provided, and this already treats s="string argument with spaces" as one block. I'd like to handle an interactive Console input the same way, but wasn't able to find an equivalent function...

Do I really have to parse it myself? My straight forward approach would be to read the whole line and splitting at spaces, but then I'd have to handle the case for string arguments in quotes...

EDIT: Maybe some clarification: I'm searching for out-of-the-box string argument parser that respects string literals in quotes, such that I receive the same results as when using the same input as command line arguments. Yes, I can split it myself, e.g. using RegEx, but I was wondering if there isn't something I can use, since I receive the command line arguments that way.

7
  • 1
    "Do I really have to parse it myself?" - yes, but there are many helpful libraries for this. If all you need is delimited strings then you could even use a regular-expression (handling escape-sequences is more difficult though). Commented Jul 13, 2018 at 7:58
  • Yeah I'd probably work with RegEx if there isn't a ready made function for this Commented Jul 13, 2018 at 8:00
  • Yep - removed the comment. :o) Commented Jul 13, 2018 at 8:04
  • Nothing can possibly work 'out of the box', unless you're following some prescribed method. Most language processors utilise some form of stack and heap (hence my pointing out the split function). This all depends on how complex your needs are. Commented Jul 13, 2018 at 8:07
  • @Paul I want the same behaviour in string splitting, as windows/the apllication does when receiving command line arguments... not more, not less Commented Jul 13, 2018 at 8:11

1 Answer 1

2

If you want you can make a code that parses the command line. But there are many libraries that you can use for this.

There is a very good command line library: 'https://github.com/commandlineparser/commandline'

It is very easy to use and I hopes this helps.

You must create a 'options' class with all options provided. To declare a option you use the 'option' attribute:

[Option(char shortoption, string longoption, Required = bool,  MetaValue = string, Min = int, Seperator = char, SetName = string)]
public <type> <name> { get; set; }

Then you can parse the string array to your 'options' class and you can read the options from the class variables.

Example:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using CommandLine;
namespace ConsoleApp1
{
    //Declare some options
    public class Options
    {
        //Format:
        //[Option(char shortoption, string longoption, Required = bool,  MetaValue = string, Min = int, Seperator = char, SetName = string)]
        //public <type> <name> { get; set; }

        [Option('r', "read", Required = true, HelpText = "Filename", Separator = ' ')]
        public IEnumerable<string> InputFiles { get; set; }

        [Option('e', "echo", Required = true, HelpText = "Echo message")]
        public string echo { get; set; }

    }
    class Program
    {
        static void Main(string[] args)
        {
            bool s = true;
            CommandLine.Parser.Default.ParseArguments<Options>(args).WithNotParsed<Options>((errs) => 
            {
                foreach (Error e in errs)
                {
                    Console.WriteLine("ERROR " + e.Tag.ToString());
                    s = e.StopsProcessing ? false : s;
                }
                if(!s)
                {
                    return;
                }
            }).WithParsed<Options>(opts => {
                Console.WriteLine(opts.echo);
                foreach(string filename in opts.InputFiles)
                {
                    Console.WriteLine(File.ReadAllText(filename));
                }
            });

        }
    }
}

Console:

ConsoleApp1\bin\Debug>ConsoleApp1.exe -r helps.txt sayhello.txt -e "Thanks for reading"
Thanks for reading
I hope this helps
Hello world

ConsoleApp1\bin\Debug>ConsoleApp1.exe -r -fds fds fds-f dsf -
ConsoleApp1 1.0.0.0
Copyright ©  2018
ERROR(S):
Option 'f' is unknown.
Required option 'e, echo' is missing.

  -r, --read    Required. Filename

  -e, --echo    Required. Echo message

  --help        Display this help screen.

  --version     Display version information.

ERROR UnknownOptionError
ERROR MissingRequiredOptionError

ConsoleApp1\bin\Debug>ConsoleApp1.exe -e f
ConsoleApp1 1.0.0.0
Copyright ©  2018
ERROR(S):
Required option 'r, read' is missing.

  -r, --read    Required. Filename

  -e, --echo    Required. Echo message

  --help        Display this help screen.

  --version     Display version information.

ERROR MissingRequiredOptionError

ConsoleApp1\bin\Debug>ConsoleApp1.exe -r helps.txt sayhello.txt -e ":)"
:)
I hope this helps
Hello world

ConsoleApp1\bin\Debug>

How do I install it?

Go to View -> Other windows -> Package Manager Console

Enter the command:

Install-Package CommandLineParser -Version 2.2.1 -ProjectName <yourprojectname>

Github:

https://github.com/commandlineparser/commandline

I hope this helps.

Read this: Split string containing command-line parameters into string[] in C#. Windows already import that function. (split command args)

But you can also make your own (simple function that not split between "):

static string[] ParseArguments(string commandLine)
    {
        char[] parmChars = commandLine.ToCharArray();
        bool inQuote = false;
        for (int index = 0; index < parmChars.Length; index++)
        {
            if (parmChars[index] == '"')
                inQuote = !inQuote;
            if (!inQuote && parmChars[index] == ' ')
                parmChars[index] = '\n';
        }
        return (new string(parmChars)).Split('\n');
    }
Sign up to request clarification or add additional context in comments.

4 Comments

this still works with command line parameters, but is there a way to use it interactively? As far as I see, the magic happens wiht CommandLine.Parser.Default.ParseArguments<Options>(args), which already requires a correct string array - and that's excatly what I'm missing
Read this for your solution: stackoverflow.com/questions/298830/…
Oh well, i was missing the right keywords for my search, this is exactly what i was searching for. I voted to close this question.
You do not give me the points :/. Thanks that i can help you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.