commandline
commandline copied to clipboard
Handling argument values that start with dash
I'm trying to parse a command line that looks like this:
program.exe --arg "-test"
but it returns this error
Option 't' is unknown.
using System;
using System.Linq;
using CommandLine;
class Program
{
static void Main(string[] args)
{
var cmdLine = Parser.Default.ParseArguments<Options>(args);
if (cmdLine.Errors.Any())
Console.Error.WriteLine(cmdLine.Errors);
}
}
class Options
{
[Option]
public string Arg { get; set; }
}
Well there's a strange little oddity. Technically, that's "expected behavior" based on the argument array that you're passing in to the parser, but since one of the primary uses of this library is to, well, parse arguments, it's probably worth devising a way of handling this situation.
See, .Net already has its own argument parser, except all it does is turn a single string (the arguments past program.exe
) into a string array (args
). It's the same code that turns program.exe --arg "multi word argument"
into an array with two elements. And most importantly, it drops the quotes in the process. If you print out each argument in args
, you'll notice that you get identical results whether you call program.exe --arg -test
or program.exe --arg "-test"
since they're already separated out into arguments by .Net (or more likely by your shell).
In general, this problem cannot be solved if you continue to use the arguments provided by the Main
function since it strips out those quotes which are critical to differentiate between a literal and an argument. The best alternative would be to provide a function to manually tokenize Environment.CommandLine.
In this specific case it's possible to solve the issue using the "double dash" setting. This causes all values after a --
token to be consumed as literals even if they contain dashes (like -test
).
The code looks like this:
var parser = new Parser (settings => {
settings.EnableDashDash = true;
});
var cmdLine = parser.ParseArguments<Options> (args);
And when you call the executable with a value with a dash, use this:
program.exe --arg -- -test
arg
has to be the last argument, of course, so it's a bit inconvenient but in cases where no values begin with a dash you don't need to do anything special (program.exe --arg myvalue
)
It is also possible to demand some sort of escaping for starting dash and process it internally