Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing a repeated group

Tags:

regex

.net-2.0

I am attempting to parse a string like the following using a .NET regular expression:

H3Y5NC8E-TGA5B6SB-2NVAQ4E0

and return the following using Split: H3Y5NC8E TGA5B6SB 2NVAQ4E0

I validate each character against a specific character set (note that the letters 'I', 'O', 'U' & 'W' are absent), so using string.Split is not an option. The number of characters in each group can vary and the number of groups can also vary. I am using the following expression:

([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}

This will match exactly 3 groups of 8 characters each. Any more or less will fail the match. This works insofar as it correctly matches the input. However, when I use the Split method to extract each character group, I just get the final group. RegexBuddy complains that I have repeated the capturing group itself and that I should put a capture group around the repeated group. However, none of my attempts to do this achieve the desired result. I have been trying expressions like this:

(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}

But this does not work.

Since I generate the regex in code, I could just expand it out by the number of groups, but I was hoping for a more elegant solution.


Please note that the character set does not include the entire alphabet. It is part of a product activation system. As such, any characters that can be accidentally interpreted as numbers or other characters are removed. e.g. The letters 'I', 'O', 'U' & 'W' are not in the character set.

The hyphens are optional since a user does not need top type them in, but they can be there if the user as done a copy & paste.

like image 690
Mike Thompson Avatar asked Jul 16 '26 22:07

Mike Thompson


2 Answers

BTW, you can replace [ABCDEFGHJKLMNPQRSTVXYZ0123456789] character class with a more readable subtracted character class.

[[A-Z\d]-[IOUW]]

If you just want to match 3 groups like that, why don't you use this pattern 3 times in your regex and just use captured 1, 2, 3 subgroups to form the new string?

([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}

In PHP I would return (I don't know .NET)

return "$1 $2 $3";
like image 113
Imran Avatar answered Jul 18 '26 22:07

Imran


I have discovered the answer I was after. Here is my working code:

    static void Main(string[] args)
    {
        string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*$";
        string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
        Regex re = new Regex(pattern);
        Match m = re.Match(input);

        if (m.Success)
            foreach (Capture c in m.Groups["group"].Captures)
                Console.WriteLine(c.Value);
    }
like image 28
Mike Thompson Avatar answered Jul 18 '26 22:07

Mike Thompson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!