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.

Florian Koch
  • 1,372
  • 1
  • 30
  • 49
  • 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). – Dai Jul 13 '18 at 07:58
  • Yeah I'd probably work with RegEx if there isn't a ready made function for this – Florian Koch Jul 13 '18 at 08:00
  • Yep - removed the comment. :o) – Paul Jul 13 '18 at 08: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. – Paul Jul 13 '18 at 08:07
  • @Paul I want the same behaviour in string splitting, as windows/the apllication does when receiving command line arguments... not more, not less – Florian Koch Jul 13 '18 at 08:11
  • I would have thought that splitting would be perfect for you, then... – Paul Jul 13 '18 at 08:13
  • Splitting would give me an array that contains `s="string` `argument` `with` `spaces"` separately, that's not what I get in `Main(args)` – Florian Koch Jul 13 '18 at 08:14

1 Answers1

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');
    }
SmileDeveloper
  • 366
  • 3
  • 10
  • 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(args)`, which already requires a correct string array - and that's excatly what I'm missing – Florian Koch Jul 13 '18 at 08:40
  • 2
    Read this for your solution: https://stackoverflow.com/questions/298830/split-string-containing-command-line-parameters-into-string-in-c-sharp – SmileDeveloper Jul 13 '18 at 09:14
  • 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. – Florian Koch Jul 13 '18 at 09:29
  • You do not give me the points :/. Thanks that i can help you. – SmileDeveloper Jul 13 '18 at 11:07