nblackburn nblackburn - 3 months ago 9
Javascript Question

Regular expression only returning first group

Probably something simple but i am trying to return the capture groups from this regex...

const expression = /^\/api(?:\/)?([^\/]+)?\/users\/([^\/]+)$/g


The code i am using to do this is the following...

const matchExpression = (expression, pattern) => {

let match;
let matches = [];

while((match = expression.exec(pattern)) != null) {
matches.push(match[1]);
};

return matches;
};


I am expecting the following result when matched against
/api/v1/users/1
...

['v1', '1']


But instead only seem to get one result which is always the first group.

The expression itself is fine and has been tested across multiple services but can't seem to figure out why this is not working as expected.

Any help would be hugely appreciated.

Answer

You must make sure you add the second capturing group contents to the resulting array:

while((match = expression.exec(pattern)) != null) {
     matches.push(match[1]);
     matches.push(match[2]); // <- here
};

Since you are matching an entire string, you can use a /^\/api(?:\/)?([^\/]+)?\/users\/([^\/]+)$/ regex (since you are matching a whole string you need no g global modifier) and reduce the code to:

const matchExpression = (expression, pattern) => {    
    let matches = pattern.match(expression);
    if (matches) {
        matches = matches.slice(1);
    }
    return matches;
};

The point is that you can use String#match with a regex without global modifier to access capturing group contents.

Demo:

var expr = /^\/api(?:\/)?([^\/]+)?\/users\/([^\/]+)$/;
var matches = "/api/v1/users/1".match(expr);
if (matches) {
  console.log(matches.slice(1));           
}

Comments