JS Regex multiple capturing groups return all matches

Viewed 2504

I'm trying to create a regex to extract data from the string. My sample string: dn1:pts-sc1.1. Format of a data I expect: ['pts', 'sc', '1.1'] so basically every set of letters after : and the numbers from the end.

What i have right now:

/^[^:]+:(?:([a-z]+)-?)+([\d\.]+)$/g

Unfortunately, it returns only last set of letters. ['sc', '1.1']

I also tried to add + to the first capturing group:

/^[^:]+:(?:([a-z]+)+-?)+([\d\.]+)$/g

The result in the same. Only difference in that regex101 gives me this comment:

A repeated capturing group will only capture the last iteration. Put a capturing group around the repeated group to capture all iterations or use a non-capturing group instead if you're not interested in the data

--edit

examples of input string:

  • dn2.33:sc-pts-tt-as3.43
  • dn2.33:sc3.43
  • dn2.33:sc-tt-as3.43

So basically I don't know the number of letter groups.

1 Answers

You may not get arbitrary number of groups, their number is specified by the number of capturing groups in your pattern. You may instead match and capture the --separated values into 1 group and then split it with - to get individual items and build the result dynamically:

var strs = ['dn2.33:sc-pts-tt-as3.43','dn2.33:sc3.43','dn2.33:sc-tt-as3.43'];
var rx = /^[^:]+:([a-z]+(?:-[a-z]+)*)([\d.]+)$/; // Define the regex
for (var s of strs) {
  var res = [];             // The resulting array variable
  var m = rx.exec(s);       // Run the regex search
  if (m) {                  // If there is a match...
    res = m[1].split('-');  // Split Group 1 value with - and assign to res
    res.push(m[2]);         // Add Group 2 value to the resulting array
  }
  console.log(s, "=>", res);
}

The pattern - ^[^:]+:([a-z]+(?:-[a-z]+)*)([\d.]+)$ - will match the following:

  • ^ - start of string
  • [^:]+ - 1+ chars other than :
  • : - a colon
  • ([a-z]+(?:-[a-z]+)*) - Group 1 (it will be abc-def-ghij...): 1 or more letters followed with 0+ consecutive sequences of - and 1+ letters (add /i modifier to make the pattern case insensitive)
  • ([\d.]+) - Group 2 (it can be just "push"ed into to the resulting array as m[2]): 1 or more digits or .
  • $ - end of string.
Related