I want to match a portion of a string using a regular expression and then access that parenthesized substring:
var myString = "something format_abc"; // I want "abc"
var arr = /(?:^|\s)format_(.*?)(?:\s|$)/.exec(myString);
console.log(arr); // Prints: [" format_abc", "abc"] .. so far so good.
console.log(arr[1]); // Prints: undefined (???)
console.log(arr[0]); // Prints: format_undefined (!!!)
What am I doing wrong?
I've discovered that there was nothing wrong with the regular expression code above: the actual string which I was testing against was this:
"date format_%A"
Reporting that "%A" is undefined seems a very strange behaviour, but it is not directly related to this question, so I've opened a new one, Why is a matched substring returning "undefined" in JavaScript?.
The issue was that console.log
takes its parameters like a printf
statement, and since the string I was logging ("%A"
) had a special value, it was trying to find the value of the next parameter.
You can access capturing groups like this:
And if there are multiple matches you can iterate over them:
Your syntax probably isn't the best to keep. FF/Gecko defines RegExp as an extension of Function.
(FF2 went as far as
typeof(/pattern/) == 'function'
)It seems this is specific to FF -- IE, Opera, and Chrome all throw exceptions for it.
Instead, use either method previously mentioned by others:
RegExp#exec
orString#match
.They offer the same results:
There is no need to invoke the
exec
method! You can use "match" method directly on the string. Just don't forget the parentheses.Position 0 has a string with all the results. Position 1 has the first match represented by parentheses, and position 2 has the second match isolated in your parentheses. Nested parentheses are tricky, so beware!
A one liner that is practical only if you have a single pair of parenthesis:
Terminology used in this answer:
someString.match(regexPattern)
./format_(.*?)/g
, where(.*?)
would be a matched group.) These reside within matched patterns.Description
To get access to the matched groups, in each of the matched patterns, you need a function or something similar to iterate over the match. There are a number of ways you can do this, as many of the other answers show. Most other answers use a while loop to iterate over all matched patterns, but I think we all know the potential dangers with that approach. It is necessary to match against a
new RegExp()
instead of just the pattern itself, which only got mentioned in a comment. This is because the.exec()
method behaves similar to a generator function – it stops every time there is a match, but keeps its.lastIndex
to continue from there on the next.exec()
call.Code examples
Below is an example of a function
searchString
which returns anArray
of all matched patterns, where eachmatch
is anArray
with all the containing matched groups. Instead of using a while loop, I have provided examples using both theArray.prototype.map()
function as well as a more performant way – using a plainfor
-loop.Concise versions (less code, more syntactic sugar)
These are less performant since they basically implement a
forEach
-loop instead of the fasterfor
-loop.Performant versions (more code, less syntactic sugar)
I have yet to compare these alternatives to the ones previously mentioned in the other answers, but I doubt this approach is less performant and less fail-safe than the others.