# Regular Expression matching customer number strings

Using VB.NET, I have created an AddIn for Autodesk Inventor and the customer has a bunch of drawing number strings which follow this sort of scheme:

1. P01867-13-TP09-001-4950-1775-1175-895-1125-835
2. P01867-13-TP09-002-4950-1775-1045-895-1035
3. P01867-13-TP02-019-L-1137-275-852-102
4. P01867-13-TP02-019-L-1137-275-852-102
5. P01867-13-TP02-019-R-1137-275-852-102
6. P01867-13-TP02-021-L-1137-1055-1372
7. P01867-13-TP02-021-L-1137-535-1027
8. P01867-13-TP02-021-L-1137-795-1184
9. P01867-13-TP02-021-R-1137-1055-1372
10. P01867-13-TP02-021-R-1137-535-1027
11. P01867-13-TP02-021-R-1137-795-1184
12. P01867-13-TP02-025-L-1137-1315-1581
13. P01867-13-TP02-025-R-1137-1315-1581
14. P01867-13-TP03-005
15. P01867-13-TP02-019-L-1137-275
16. P01867-13-TP02-019-R-1137-275
17. P01867-13-TP02-019-R-1137
18. P01867-13-TP02-019-L-1137

In order to account for these groups of three digits within the variations I have created the following regex:

(\w*\d*-\d*-\w*\d*-\d*-\w-)(\d*)-(\d*)-(\d*)-(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-\w-)(\d*)-(\d*)-(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-\w-)(\d*)-(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-\w-)(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-\w-)(\d*)|(\w*\d*-\d*-\w*\d*-\d*-)(\d*)-(\d*)-(\d*)-(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-)(\d*)-(\d*)-(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-)(\d*)-(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-)(\d*)-(\d*)|(\w*\d*-\d*-\w*\d*-\d*-)(\d*)|(\w*\d*-\d*-\w*\d*-\d*)|.*(\w*\d*-\d*-)(\d*)-(\d*)-(\d*)-(\d*)-(\d*)|.*(\w*\d*-\d*-)(\d*)-(\d*)-(\d*)-(\d*)|.*(\w*\d*-\d*-)(\d*)-(\d*)-(\d*)|.*(\w*\d*-\d*-)(\d*)-(\d*)|.*(\w*\d*-\d*-)(\d*)|.*(\w*\d*-\d*-\w-)(\d*)-(\d*)-(\d*)-(\d*)-(\d*)|.*(\w*\d*-\d*-\w-)(\d*)-(\d*)-(\d*)-(\d*)|.*(\w*\d*-\d*-\w-)(\d*)-(\d*)-(\d*)|.*(\w*\d*-\d*-\w-)(\d*)-(\d*)|.*(\w*\d*-\d*-\w-)(\d*)


I now have to add the capability of looking for a sixth group of digits so figured I would ask here if there is a method within regex (which I may have overlooked) that will allow me to improve upon/simplify the above monster.

^P\d{5}-13-TP\d{2}-\d{3}(-(L|R|\d{4})(-\d{3,4})*)?$ Your current regex is WAY too forgiving. First of all, every one of your example starts with a P followed by some numbers, but you accept ANY COMBINATION of letters at the beginning. I'm assuming that ALEX01867-13-TP02-019-L-1137 isn't a valid key, so you should take steps to reject it by using hungry quantifiers as little as possible (*, +). Using \d{3,4} matches a digit between 3 and 4 times, so that will let you limit the sort of input you accept. The same goes for the 5th group - according to your examples, it's either L, R, or 4 digits. In Regex, that looks like this: (L|R|\d{4}) Next, you are using alternation (option1|option2) to capture the different "forms" your string comes in as, but you are repeating a bunch of stuff (for example, the \w*\d* at the beginning). You can limit the scope of the alternation by surrounding it in brackets (()). You can see this in action with the (L|R|\d{4}) example - that whole bracket group becomes a single token that matches somewhere in a string (or doesn't). Sometimes the string ends after the 4th group (Before the L/R group), and sometimes it doesn't. Instead of using alternation to solve this, which makes the regex VERY long, you can just surround the entire regex AFTER that point in brackets with a question mark (an-(example)?). This makes the entire second part optional. Finally, your problem asks if there is a simple method to improve the regex. By ending it in (-\d{3,4})* you can match ANY length of additions to the end, assuming the all come in the form -015 or -1992 or whatever. If you knew that there was always a max of 15 numbers added to the end, you could change that star (*) to a max quantifier ({,15}). If sometimes the number only has two digits, change the {3,4} to {2,4}, etc. See it in action here • Thanks for the explanation/solution @devon-parsons! I do need to group each of the three-digit strings into groups in order to be able to retrieve Dimension A, B, C, D etc. from the strings that continue after the L or R values - does that make sense? – AlexFielder Oct 16 '15 at 13:15 • With repeated groups, you can only capture the final group that gets captured - so currently, your first line would capture -835. If you need ALL of them, you can capture EVERYTHING after the L/R by putting brackets around it and using your programming language of choice to split on the - characters to get the different groups. – Devon Parsons Oct 16 '15 at 14:06 • To be clear, that means you would surround (-\d{3,4})* with brackets to make the entire string read ^P\d{5}-13-TP\d{2}-\d{3}(-(L|R|\d{4})((-\d{3,4})*))?$. One of the capture groups will look like -001-002-003-004 etc. if you feel like it, look up non-capturing groups (?:) to tidy it up. – Devon Parsons Oct 16 '15 at 14:10