0

I've been trying to write a regex to stictly match the following patterns - 3+, 3 months +, 3+ months, 3m+, 3 years +, 3y+, 3+ years. I've written a pattern - [0-9]{1,2}\s?(m|months?|y|years?)?\s?\+ which works for most of the cases exept the 3+ months & 3+ years here it matches just the 3+ part and not the month part. I want to use the matched string somewhere and this causes an issue. To accomodate this I tried adding another group to make the regex look like [0-9]{1,2}\s?(m|months?|y|years?)?\s?\+ (m|months?|y|years?)\s|$ but this is also matching for 6+ math. Can someone help me with what the issue is here, also can this regex be improved?

I can use multiple regex to solve different different use cases, but I wanted to achieve this using only 1 regex.

Thanks

2
  • So 6+ math shouldn't match at all or should match 6+ out out it? Are all inputs on separate lines?
    – anubhava
    Commented Mar 13, 2019 at 6:25
  • Only 6+ should match here & not 6+ m from math, and for a case 6+ months it should be a complete match and not only 6+ Commented Mar 13, 2019 at 6:43

3 Answers 3

2

UPDATED:

I overlooked the strictness requirement. Something that helps me figuring out these problems is breaking the pattern down in a logic tree of sorts, like so:

  1. Only XX months allowed
  2. Only XX years allowed - \d{1,2}
  3. If ## followed by a +
    • It must be followed by \s*(months|years)
  4. If ## followed by a [my]
    • It must be followed by \s*\+
  5. Close it off with $

That gets us on the right track to what we want. Again, it still permits undesired cases, but just revisit that thought exercise, tinker with the conditionals, and try to find common components that restrict the full regex to neat grouping of stricter patterns.

This should be closer to the strict solution you’re looking for:

\d{1,2}\s*([my]?\+|\+?\s*(months|years)|(months|years)\s*\+?)\s*$

===========================

ORIGINAL POST:

Here’s a first pass at a condensed version of what you want: \d{1,2}[\+my]?\s*(months|years)?\s*\+?

Here’s a breakdown of the approach I took:

(\d{1,2})

^ Accommodate any two numbers (your approach is fine, \d means any number 0-9, saves a few characters)

([\+my]?\s*)

^ The characters following the given number may be m, y, or + followed by any number of spaces.

(months|years)?

^ We’ve accounted for all spaces with the previous piece of regex, so lets just say there might be months|years at this point.

(\s*\+?)

^ Last potential symbol is a +, but it might have several spaces in front of it.

4
  • This won't work for a case where we have no + present for example it will match for 6m where it should not have. Commented Mar 13, 2019 at 6:59
  • I have updated the solution. Eager to solve the given patterns, I ignored some of the more lenient logic in the regex. Commented Mar 13, 2019 at 7:12
  • The updated solution matches for 6 months in 6 months + & 6+ in 6+ months if I remove the $ and I can't have a $ in my pattern, Apologies I know the updating specifics are really troublesome. Commented Mar 13, 2019 at 8:56
  • I derived this from your answer to match all the required formats - \d{1,2}\s*([my]?\+|\+?\s*(months|years)|(months|years)\s*\+?)\s*\+?(months|years)? Commented Mar 13, 2019 at 10:00
0

Try the following regex

((?:\d{1,2}\+ (?:months|years))|(?:\d{1,2}\+)|(?:\d{1,2} (?:months|years) \+)|(?:\d{1,2}(?:m|y)\+))
0

You may use this regex with optional matches:

\d{1,2}\+?(?:\s?(?:months?|years?|[my])\b\s?\+?)?

RegEx Demo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.