28
\$\begingroup\$

In our console app, the parsing of application arguments is done like so:

using System.Linq;

namespace Generator
{
    internal class Program
    {
        public static void Main(string[] args)
        {
            var param1 = args.SingleOrDefault(arg => arg.StartsWith("p1:"));
            if (!string.IsNullOrEmpty(param1))
            {
                param1  = param1.Replace("p1:", "");
            }
            //...
        }
    }
}

It's supposed to be called like this:

`Generator.exe p1:somevalue`

Is there a better/simpler way to parse arguments?

\$\endgroup\$

closed as off-topic by Mast, Sᴀᴍ Onᴇᴌᴀ, Stephen Rauch, Dannnno, Phrancis Apr 11 '18 at 20:17

This question appears to be off-topic. The users who voted to close gave this specific reason:

  • "Lacks concrete context: Code Review requires concrete code from a project, with sufficient context for reviewers to understand how that code is used. Pseudocode, stub code, hypothetical code, obfuscated code, and generic best practices are outside the scope of this site." – Mast, Sᴀᴍ Onᴇᴌᴀ, Stephen Rauch, Dannnno, Phrancis
If this question can be reworded to fit the rules in the help center, please edit the question.

27
\$\begingroup\$

I'd recommend taking advantage of the excellent Mono.Options module. It's a single .cs file you can drop in to your solution and get full-featured parsing of GNU getopt-style command lines. (Things like -x -y -z, which is equivalent to -xyz, or -k value, or --long-opt, and so forth.)

\$\endgroup\$
  • \$\begingroup\$ from 2018: Microsoft added their own code to the file. Now you CAN NOT use it as a separated file. Thanks MS. This is the latest tag without MS's intervention I've found \$\endgroup\$ – maxkoryukov Apr 13 '18 at 16:40
  • 2
    \$\begingroup\$ @maxkoryukov I don't get your logic. It's still licensed under the MIT license, which explicitly says it can be copied in part or in whole, as long as the license is included with it. So as of this writing in 2019 you can still take this file on its own. Unless you have something about irrationally avoiding everything Microsoft has ever touched, in which case you should know that StackExchange runs on Microsoft software. \$\endgroup\$ – Nic Hartley Jan 12 at 20:32
  • \$\begingroup\$ @NicHartley, you are right, it is still MIT-licensed. Sorry, but I don't remember what I meant then, so I can't explain my comment now... Yes, I don't like the MS-development way and their style in the software world, overall. But who am I ))) \$\endgroup\$ – maxkoryukov Jan 14 at 16:54
  • \$\begingroup\$ @maxkoryukov urgh, sorry for my tone there -- I genuinely didn't mean any sarcasm, but rereading my comment it really sounded like it. And yeah, it's perfectly fair to dislike Microsoft. My issue is just with people avoiding everything they've ever had contact with, even indirectly by someone becoming a developer for them, because of some "taint" that they have, and (as it's been MIT-licensed the whole time) that's what I immediately jumped to. I guess I like imagining the worst of people. Sorry :( \$\endgroup\$ – Nic Hartley Jan 14 at 17:00
  • 1
    \$\begingroup\$ @NicHartley don't apologize;) there was an error in my comment (and it is still there) — I can't explain that comment in any other way. And I don't know why I wrote that comment. Mono.Options is still a decent piece of C# code, in spite of the fact of MS interventions \$\endgroup\$ – maxkoryukov Jan 14 at 17:44
23
\$\begingroup\$

With such an implementation you will have to repeat yourself for each param.

Alternative:

var parsedArgs = args
    .Select(s => s.Split(new[] {':'}, 1))
    .ToDictionary(s => s[0], s => s[1]);
string p1 = parsedArgs["p1"];
\$\endgroup\$
  • 1
    \$\begingroup\$ +1: I would have used '='. And check that arguments are prefixed with '--'. And what about where the value is the next argument not in the same argument? \$\endgroup\$ – Martin York Jan 28 '11 at 18:19
  • \$\begingroup\$ @Martin why would you prefix arguments with '--'? \$\endgroup\$ – frennky Jan 28 '11 at 18:38
  • 1
    \$\begingroup\$ @frennky: Its sort of a standard for command line arguments (--<longName> or -<shortName>). It separates flags (which modify behavior) from inputs/outputs. But re-reading your original question I was over generalizing and this is not what you want. \$\endgroup\$ – Martin York Jan 28 '11 at 20:15
  • \$\begingroup\$ @frennky - I agree with Martin, if you are writing an application which somebody (except you) will use then you should read about console argument standarts. As far as I know '--' is kind of *nix style, in windows it is more about slashes. \$\endgroup\$ – Snowbear Jan 28 '11 at 20:22
4
\$\begingroup\$

There's a related question on Stack Overflow. There, the consensus seems to be Mono.Options as already suggested here by josh3736.

\$\endgroup\$
  • \$\begingroup\$ Read further down the list of answers on that SO question and you'll see that ndesk.org/Options has 2x the upvotes of the accepted answer. \$\endgroup\$ – Handcraftsman Mar 4 '11 at 17:00
  • 1
    \$\begingroup\$ Actually, the answer you refer to says "I would strongly suggest using NDesk.Options (Documentation) and/or Mono.Options (same API, different namespace)." \$\endgroup\$ – Don Kirkby Mar 4 '11 at 18:00
2
\$\begingroup\$

I usually don't use complex command line arguments, so I use a very Simple Command Line Arguments Parser, but it can be used as a foundation for your own application specific parameter presenter.

\$\endgroup\$
1
\$\begingroup\$

You could use foreach for iterating through the agruments and then for your argument with index 1 you could use regular expression to retrieve parsed text after p1:

\$\endgroup\$
  • 1
    \$\begingroup\$ I was hoping to avoid using loops. As for Regex, I think it would be too much, the pattern is quite simple. \$\endgroup\$ – frennky Jan 28 '11 at 18:36
-2
\$\begingroup\$

Please check solution from link. IT uses linq. It short and reuseble in my opinion. Provides extension method so you just do somethink like:

args.Process(
           () => Console.WriteLine("Usage is switch1=value1,value2 switch2=value3"),
           new CommandLine.Switch("switch1",
               val => Console.WriteLine("switch 1 with value {0}",
                   string.Join(" ", val))),
           new CommandLine.Switch("switch2",
               val => Console.WriteLine("switch 2 with value {0}",
                   string.Join(" ", val)), "s1"));
   }

for details please visit my blog

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.