3

I'm stuck with regular expressions. The program is a console application written in C#. There are a few commands. I want to check the arguments are right first. I thought it'll be easy with Regex but couldn't do that:

var strArgs = "";

foreach (var x in args)
{
    strArgs += x + " ";
}
if (!Regex.IsMatch(strArgs, @"(-\?|-help|-c|-continuous|-l|-log|-ip|)* .{1,}"))
{
    Console.WriteLine("Command arrangement is wrong. Use \"-?\" or \"-help\" to see help.");
    return;
}

Usage is:

program.exe [-options] [domains]

The problem is, program accepts all commands. Also I need to check "-" prefixed commands are before the domains. I think the problem is not difficult to solve.

Thanks...

BrunoLM
  • 97,872
  • 84
  • 296
  • 452
PythEch
  • 932
  • 2
  • 9
  • 21

6 Answers6

4

Since you will end up writing a switch statement to process the options anyway, you would be better off doing the checking there:

switch(args[i])
{
case "-?": ...
case "-help": ...
...
default:
  if (args[i][0] == '-')
    throw new Exception("Unrecognised option: " + args[i]);
}
Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
2

First, to parse command line arguments don't use regular expressions. Here is a related question that I think you should look at:

But for your specific problem with your regular expression - the options are optional and then you match against a space followed by anything at all, where anything can include for example invalid domains and/or invalid options. So far example this is valid according to your regular expression:

program.exe -c -invalid

One way to improve this by being more precise about the allowed characters in a domain rather than just matching anything.

Another problem with your regular expressions is that you don't allow spaces between the switches. To handle that you probably want something like this:

(?:(?:-\?|-help|-c|-continuous|-l|-log|-ip) +)*

I'd also like to point out that you should use string.Join instead of the loop you are currently using.

string strArgs = string.Join(" ", args);
Community
  • 1
  • 1
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
1

Don't reinvent the wheel, handling command line arguments is a solved problem.

I've gotten good use out of the Command Line Parser Library for .Net.

quentin-starin
  • 26,121
  • 7
  • 68
  • 86
  • I've never actually seen that library, but I like the idea. Thanks for sharing. Now I have a good library to goto for attributes examples too when I want to explain them to someone ;) – jcolebrand Sep 09 '10 at 15:28
0

Actually the easiest way to achieve command line argument parsing is to create a powershell commandlet. That gives you a really nice way to work with arguments.

Bernd
  • 539
  • 3
  • 10
0

I have been using this function with success... perhaps it will be useful for someone else...

First, define your variables:

private string myVariable1;
private string myVariable2;
private Boolean debugEnabled = false;

Then, execute the function:

loadArgs();

and add the function to your code:

    private void loadArgs()
    {
        const string namedArgsPattern = "^(/|-)(?<name>\\w+)(?:\\:(?<value>.+)$|\\:$|$)";
        System.Text.RegularExpressions.Regex argRegEx = new System.Text.RegularExpressions.Regex(namedArgsPattern, System.Text.RegularExpressions.RegexOptions.Compiled);
        foreach (string arg in Environment.GetCommandLineArgs())
        {
            System.Text.RegularExpressions.Match namedArg = argRegEx.Match(arg);
            if (namedArg.Success)
            {
                switch (namedArg.Groups["name"].ToString().ToLower())
                {
                    case "myArg1":
                        myVariable1 = namedArg.Groups["value"].ToString();
                        break;
                    case "myArg2":
                        myVariable2 = namedArg.Groups["value"].ToString();
                        break;
                    case "debug":
                        debugEnabled = true;
                        break;
                    default:
                        break;
                }
            }
        }
    }

and to use it you can use the command syntax with either a forward slash "/" or a dash "-":

myappname.exe /myArg1:Hello /myArg2:Chris -debug
Dscoduc
  • 7,714
  • 10
  • 42
  • 48
0

This regex parses the command line arguments into matches and groups so that you can build a parser based on this regex.

((?:|^\b|\s+)--(?<option_1>.+?)(?:\s|=|$)(?!-)(?<value_1>[\"\'].+?[\"\']|.+?(?:\s|$))?|(?:|^\b)-(?<option_2>.)(?:\s|=|$)(?!-)(?<value_2>[\"\'].+?[\"\']|.+?(?:\s|$))?|(?<arg>[\"\'].+?[\"\']|.+?(?:\s|$)))

This Regex will parse the Following and works in almost all the languages

--in-argument hello --out-stdout false positional -x
--in-argument 'hello world"
"filename"
--in-argument="hello world'
--in-argument='hello'
--in-argument hello
"hello"
helloworld
--flag-off
-v
-x="hello"
-u positive
C:\serverfile
--in-arg1='abc' --in-arg2=hello world c:\\test

Try on Regex101