horse shoe
horse shoe

Reputation: 74

Regular expression ignore capturing group order

Please open following URL in chrome => https://regex101.com/r/rWLAOU/1/

Regex:

\b(f|fall|w|winter|s|spring|su|summer)\b\s*(?<!\d)(\d{4}|\d{2})(?!\d)

Test Strings:

Fall 2018
fall 18
2016 Fall
F2016
Fall2016

The Regular Expression I defined works fine for all the Test Strings except when capturing group order is swapped (2016 Fall or 16f or 18Su) Is there a way in Regular expression to ignore ordering of capturing groups of your RegExp

Upvotes: 2

Views: 349

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626853

You may use an alternation with two parts where the year and season are swapped and then grab only the matched captures:

\b(?:(f(?:all)?|w(?:inter)?|s(?:pring|u(?:mmer)?)?)\s*(\d{2}(?:\d{2})?)|(\d{2}(?:\d{2})?)\s*(f(?:all)?|w(?:inter)?|s(?:pring|u(?:mmer)?)?))\b

See the regex demo

I contracted your alternatives to make matching more efficient: all alternatives should only match at unique locations. Word boundaries seem to be enough for your case.

In JS, you may build the pattern dynamically:

var strs = ['Fall 2018','fall 18','2016 Fall','F2016','Fall2016'];
var season = "(f(?:all)?|w(?:inter)?|s(?:pring|u(?:mmer)?)?)";
var year = "(\\d{2}(?:\\d{2})?)";
var p = new RegExp("\\b(?:" + season + "\\s*" + year + "|" + year + "\\s*"+ season + ")\\b","i");
var results=[], m;
for (var s of strs) {
  m  = s.match(p);
  if (m) {
    if (m[1]) {
      console.log(m[1],":", m[2]); 
    } else {
      console.log(m[3],":", m[4]); 
    }
  }
}

Upvotes: 1

Related Questions