papiro
papiro

Reputation: 2365

JavaScript RegEx with non-capturing group exhibiting bewildering behavior

My question is very simple. Thank God because Regex's can be complex...

I have a query parameter in the url, given by ?id=0061ecp6cf0q.

I would like to match it, but only capture the part after the equals sign.

I have a regex as such:

(?:\?id=){1}([a-z0-9])+

When, in JavaScript, I have a string containing the query parameter and do a .match() on it with a regular expression object constructed from the regex above, I am returned an array of length 1 with the entry: "?id=0061ecp6cf0q".

When I do a .exec() on the regex with the query string as a parameter, I am returned an array of length 2:

array[0] = "?id=0061ecp6cf0q"
array[1] = "q"

1) Why is my non-capturing group seemingly capturing? 2) Why is "q" being captured, of all things?

Upvotes: 2

Views: 97

Answers (4)

Kyle Muir
Kyle Muir

Reputation: 3925

Copied from: How can I get query string values in JavaScript?

You don't need jQuery for that purpose. You can use just some pure JavaScript:

function getParameterByName(name) {
    name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
    var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
        results = regex.exec(location.search);
    return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}

Usage:

var prodId = getParameterByName('prodId');

Upvotes: 0

papiro
papiro

Reputation: 2365

A couple things.

Turns out my regex needed to look like this:

(?:\?id=){1}([a-z0-9]+)

with the final "+" on the inside of the capture group!! That explains why it was capturing "q". The reason string.prototype.match wasn't working as I thought it should, was because I was doing

new RegExp("(?:\\?id=){1}([a-z0-9]+)", "g")

That "g" flag (global) apparently keeps it from returning an array of the capture groups and will instead return just the match(es). Without the "g" flag it behaves like RegExp.prototype.exec http://speakingjs.com/es5/ch19.html#String.prototype.match

Upvotes: 0

wnbates
wnbates

Reputation: 753

The + to match all of the alphanumeric characters wants to be inside the capturing group.

(?:\?id=){1}([a-z0-9]+)

Upvotes: 1

Henrik Karlsson
Henrik Karlsson

Reputation: 5713

Your non-capture group is not capturing. The 0th element of the array is always the full value. If you want to capture just the value, you have to put parenthesis around what you want to capture:

> /(?:\?id=){1}([a-z0-9]+)/.exec('?id=0061ecp6cf0q')
["?id=0061ecp6cf0q", "0061ecp6cf0q"]

EDIT:

You put parenthesis around just ([a-z0-9]), which will match one character (in this case q), not the whole thing including the +.

Upvotes: 2

Related Questions