Why doesn't String.match () give the expected results when there is a global flag?

I tried this match

'/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/g) 

and received:

 ['/links/51f5382e7b7993e335000015'] 

when i was expecting:

 ['/links/51f5382e7b7993e335000015', '51f5382e7b7993e335000015'] 

I was not lucky until I removed the global flag, which I thought would not affect the results of my results!

When removing a global flag

 '/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/) 

produced by:

 [ '/links/51f5382e7b7993e335000015', '51f5382e7b7993e335000015', index: 0, input: '/links/51f5382e7b7993e335000015' ] 

This is cool, but reading the docs, I can't figure it out:

  • Why the first form did not work.
  • Why did the global flag interfere with () compliance
  • How to get the expected result without index and input properties

In JavaScript Regex and Submatches , the top answer says:

The String match () function does not return the returned groups if the global modifier is installed, as you found out.

but

 > 'fofoofooofoooo'.match(/f(o+)/g) ["fo", "foo", "fooo", "foooo"] 

seems to create captured groups just fine.

Thanks.

+6
source share
2 answers

From this msdn documentation for the matching method:

If global flag (g) is not set, the zero element of the array contains all matches, and elements 1 through n contain submatrices. This behavior is the same as exec (regular expression) (JavaScript) behavior when the global flag is not set. If the global flag is set, items 0 through n contain all matches that have occurred.

Emphasis is mine.

So in your first case :

 '/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/g) 

Since the /g modifier is installed, it will only return the complete matches that occurred, not the submatrices. This is why you just got an array with one element. Since there is only 1 match for this regular expression.

Second case :

 '/links/51f5382e7b7993e335000015'.match(/^\/links\/([0-9a-f]{24})$/) 
Modifier

/g not installed. So the array contains a complete match at index 0th . And then the elements (1st index) in the array are submatrices - in this case, the first capture group.


As for your last example :

 'fofoofooofoooo'.match(/f(o+)/g) 

Again, since the /g modifier is set, it will return all matches from the string, not the submatrix. So, in the string, the regular expression f(o+) matches 4 times:

 fo - 1st complete match (sub-match 'o' in 1st captured group ignored) foo - 2nd complete match (sub-match 'oo' ignored) fooo - 3rd complete match (sub-match 'ooo' ignored) foooo - 4th complete match (sub-match 'oooo' ignored) 

If you use the last regular expression without the /g modifier, you will get each profile as a separate element for the first match. Try:

 'fofoofooofoooo'.match(/f(o+)/) 

You'll get:

 ["fo", "o"] // With index and input element of course. 

Without /g it just stops after the first match ( fo ) and returns all matches and matches.

+3
source

According to MDN , if the g flag is not specified, it returns the same results as RegExp.exec () , which returns an array containing elements for capturing parentheses.

If the g flag is specified, it returns an array containing all matches.

This description is consistent with the examples in the question, but your two examples are apples with oranges:

  • Your β€œlink” regular expression matches the entire input line once, possibly with one captured group depending on the flag.
  • The regular expression /f(o+)/g matches multiple substrings at the input.
+1
source

Source: https://habr.com/ru/post/950483/


All Articles