fearless_fool
fearless_fool

Reputation: 35219

node.js RegExp doesn't handle multiple matches with 'g' flag?

Does Javascript's RegExp#exec() NOT handle multiple results with the 'g' flag? If not, what are the alternatives?

I have a string like this:

a*  2
b   3
c*  4

and I want to extract only those lines that have an asterisk. I've written this regexp:

/\w+\*\s+(\d+)\n/g

(i.e. it matches a word followed by a literal asterisk followed by whitespace followed by a capturing group of digits followed by newline, and has the global flag turned on).

In the delightful https://regex101.com/#javascript, applying the string to the regexp returns two matches, as expected:

Match 1
1.   '2'
Match 2
1.   '4'

But in node.js, I get this:

> match = re.exec(str)
> match
[ 'a*  2\n', '2', index: 0, input: 'a*  2\nb   3\nc*  4\n' ]

It appears the match object is not multi-dimensional, or at least, it only captures the first match.

Am I missing something fundamental? And (as I asked at the top) is there a sensible alternative?

Upvotes: 3

Views: 804

Answers (2)

craigts
craigts

Reputation: 3077

Javascript's RegExp#exec() does support multiple matches, but does not return them all at once. You need to call exec() multiple times. The docs for this functionality on MDN explains the issue and gives an example of how to use exec() for multiple matches. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec#Examples

var myRe = /ab*/g;
var str = 'abbcdefabh';
var myArray;
while ((myArray = myRe.exec(str)) !== null) {
  var msg = 'Found ' + myArray[0] + '. ';
  msg += 'Next match starts at ' + myRe.lastIndex;
  console.log(msg);
}

Upvotes: 1

Singular1ty
Singular1ty

Reputation: 2615

I'm going to preface this answer by saying that I know very little about Regex, but, I just performed my own testing and found that the issue could be with the \n in your regex.

Requiring the \n means that in a snippet like the one you posted, if there is no newline after c* 4, that line won't be matched.

\w+\*\s+(\d+) works just fine according to my tests on Regexr.

As I said, I may be off by a mile here, but that's just my thought.

Edit: The results of my testing:

/\w+\*\s+(\d+)\n/g

a*  2   [MATCH]
b   3
c*  4

And:

/\w+\*\s+(\d+)/g

a*  2   [MATCH]
b   3
c*  4   [MATCH]

Using the original, but putting a newline after c:

/\w+\*\s+(\d+)\n/g

a*  2   [MATCH]
b   3
c*  4   [MATCH]
\n

Upvotes: 1

Related Questions