Search code examples
c#regexcombinationspermutationregex-lookarounds

Is it possible to detect combinations and permutations of captured groups in a single line?


I'm trying to detect a program from the process table and I need to parse its argument in captured groups. I want to do this with a single regex, however, I don't know if it is possible if some arguments are jumbled and/or omitted.

For example, I have:

program.exe -a arg_a -b arg_b -c arg_c -d arg_d -e arg_e

But it can also be:

program.exe -c arg_c -a arg_a -b arg_b -e arg_e
program.exe -b arg_b 
program.exe -a arg_a -c arg_c -d arg_d

Now, I need to get each argument. I know I can simply have 5 sets of regex a shown below,

"program.exe(?:.*-a (?<arga>\w+)|)"
"program.exe(?:.*-b (?<argb>\w+)|)"
"program.exe(?:.*-c (?<argc>\w+)|)"
"program.exe(?:.*-d (?<argd>\w+)|)"
"program.exe(?:.*-e (?<arge>\w+)|)"

but that would take 5 iterations and I would really like to get it in a single run.

Is it possible? Would highly appreciate any insights on this.


Solution

  • You can use a regex like this that matches the whole string:

    ^program.exe(?:\s+-(?<name>[a-e]) (?<arg>\w+))+$
    

    then make use of the Captures property:

    string regex = @"^program.exe(?:\s+-(?<name>[a-e]) (?<arg>\w+))+$";
    string text = "program.exe -a arg_a -d arg_d -e arg_e -b arg_b -c arg_c";
    Match match = Regex.Match(text, regex);
    var names = match.Groups["name"];
    var args = match.Groups["arg"];
    foreach (var (name, arg) in names.Captures.Zip(args.Captures)) {
        Console.WriteLine($"{name.Value}: {arg.Value}");
        // or add these pairs to a dictionary for further processing and validation
    }
    
    /*
    a: arg_a
    d: arg_d
    e: arg_e
    b: arg_b
    c: arg_c
    */