1

I want to use RegEx in order to remove version numbers from product names. The names can look like this:

SampleProduct 2.0

They can also have parentheses around the version number:

SampleProduct (2.1)

Therefore, I tried to define a group for the version number and an alternative for the version with parentheses:

\s((?<versionNumber>\d+(\.\d+)*)|\(\k<versionNumber>\))\z

But this yields no matches. Since the pattern is quite small I tried accessing the group with an index:

\s((\d+(\.\d+)*)|\(\2\))\z

This didn't work either. By the way, in which order are nested groups indexed? Are they ordered by the occurrence of their open or closing parentheses? Anyways, none of \1, \2 and \3 yielded a match.

I tried to find out if I misunderstood a feature of Regex. When I experiment with groupings and alternatives seperately, they work as expected. But when I mix these two features, at some point it stops working and I can't spot the problem. Currently I'm successfully using the expression without the grouping to remove the version:

name = name.Substring(0, name.Length - Regex.Match(name, @"\s(\d+(\.\d+)*|\(\d+(\.\d+)*\))\z").Value.Length);

But I would like to aviod the pattern duplication.

  • In this case, there is another solution ([Balanced Groups](https://www.regular-expressions.info/balancing.html)) that do not require reuse the pattern parts, and would allow the OP to have a cleaner regex. – Edgar Hernandez Apr 15 '19 at 16:40

1 Answers1

1

If you want to avoid repeating the part of a pattern in a regex and just want to match 2.0 or (2.0) BUT not (2.0 or 2.0), you may use a conditional regex:

(\()?\d+(?:\.\d+)*(?(1)\))

See the regex demo.

If there is just one parentheses it won't become part of a match.

Details

  • (\()? - An optional capturing group #1: a ( char (if there is no (, the value of this group is null and the later (?(1)...) check will fail)
  • \d+ - 1 or more digits
  • (?:\.\d+)* - 0 or more repetitions of . and 1+ digits
  • (?(1)\)) - a conditional construct: if Group 1 matched, ) must be matched, else there is nothing to match (absent |...) else condition part means anything can follow the pattern before).
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563