I have this example string in Javascript, "246126667"
, and I want to get all the substrings that have any 2 numbers on the left and a 6 at the end, that is, ["246","126","266","666"]
, and for that I apply a match
with the regular expression [0-9]{2}6
, and the parameter g
to get the results, but it doesn't work as I want.
console.log(
"246126667".match(/[0-9]{2}6/g)
)
The problem is that instead of returning all 4 numbers, it only returns ["246","126"]
. Is it possible to solve this using regular expressions? Is there any other way?
Problem
The expression you used (
[0-9]{2}6
) is fine. The main issue of why it doesn't match overlapping characters is because the regex engine consumes the characters it matches. Therefore, after matching"126"
onthe position to attempt the next match will be:
and it will not find another 3 digits ending in
6
.Solution
A positive lookahead attempts a match, but if it matches, it returns to the position it was in before trying . That is, it does not consume characters. The syntax is
So this regex will match what you are looking for
But there is an addition: since it does not consume characters, it matches the position, and not the 3 characters that you are trying to get. For that, we use a group (we surround it with parentheses) to capture the text.
In addition, it is necessary to use
.exec()
to then get the captured text inmatch[1]
, and an extra condition to avoid infinite loops due to a known JavaScript bug.Regex
Code
To complete @Mariano's answer, I'm going to try to shed a little more light on the matter so that the topic of
aserciones positivas
.As @Mariano explained, using the following regular expression
/[0-9]{2}6/g
, these would be the operations performed by the methodmatch
youString
placed as an example:So, to prevent this from happening, you can do two things:
1 - Use the method
exec
and manipulate thelastIndex
regular expression, subtracting2
it so that the next search starts from the next character after the start of thematch
:2 - Or do what @Mariano recommended: one
aserción positiva
.But with its regular expression you would also have to manipulate the property
lastIndex
since, a positive assertion is not that it doesmatch
and returns to the beginning of thematch
but that it never moves from that place (it does not consume characters, because it is not part of thematch
). This is not a bugJavaScript
but rather we are explicitly tellingscript
it not to consume any characters. Taking the regular expression as an example/(?=(\d{2}6))/g
, let us note that it does not try to domatch
with any character, but what it does do is capture a group made up of two digits followed by a6
so we could access this capture with theexec
. Let's see what would be the steps that the method would followexec
in this regular expression:Therefore if we use the method
exec
with awhile
the call stack would be filled with anloop
infinity, to avoid this we should add one to thelastIndex
regular expression property so that the nextmatch
one looks for it from that place:It is not necessary to do the condition
match.index === regex.lastIndex
because unless we vary it, the propertylastIndex
of the regular expression will remain invariably equal to the beginning ofmatch
since no character is consumed in said expression.One method you could follow to avoid having to update the property
lastIndex
is to use a regular expression that does consume characters, for example this expression/(?=(\d{2}6))\d/g
. Note that the only thing that is different from the one that @Mariano has placed is that it does makematch
a digit, so this expression will consume characters. Let's follow the steps that the method would followexec
with this regular expression: