Regex lookahead - (?=\D*\d) VS (?=*\d)

While implementing the solution for section https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/regular-expressions/positive-and-negative-lookahead I ran into the following issue.

I started defining the lookaheads required for the password, and they looked like this originally:

/(?=.{6})(?=\d{2})/

I got 2 errors:

Your regex should match “bana12”
Your regex should match “abc123”

I started doing some tests on those particular strings and I noticed that if I try to apply the lookaheads on them individually both work, I used the following regexps:

/(?=\d{2})/
/(?=.{6})/

But they won’t work properly together unless \D* is placed in the first one like in the example you provide:

/(?=\D*\d{2})(?=.{6})/

I’m guessing there might be some kind of interaction between the different lookaheads when put together and they should not be understood as separate ‘conditions’ however I still cannot confirm this nor get to know how it works exactly and would appreciate some help on it.

Thanks in advance.

After each lookahead completes its matching, the search index returns to what value it was at the start of the lookahead match.

With /(?=\d{2})/ the lookahead starts matching from the position of the first digit, which for 'bana12' is index 4. It then searches for one more digit at index 5, which it finds. Then the index is reset to 4. Since there is nothing left to do, the test function returns true.

With /(?=.{6})(?=\d{2})/, the first lookahead starts matching from index 0 (the start of the string). After it is complete, the index returns to 0, and then the second lookahead starts matching. So if the string doesn’t have at least 6 characters and there aren’t 2 numbers at the start of the string, the test function will return false.

With /(?=\D*\d{2})(?=.{6})/, again both lookaheads start matching from index 0 of the strings bana12 and abc123 and since both make successful matches, the test function returns true.

If you have /(?=1)(?=\d{3})/.test('abc123'), both lookaheads start from index 3 (the position of '1' in 'abc123') and the test function returns true. /(?=1)(?=\d{4})/.test('abc123') returns false.

I found the article at https://medium.freecodecamp.org/regular-expressions-demystified-regex-isnt-as-hard-as-it-looks-617b55cf787 to be very helpful in understanding regex.

Also, the repl at https://stephengrider.github.io/JSPlaygrounds/ is very good for playing around with regex.

3 Likes

Thanks for the explanation Joops, really helpful, it makes perfect sense when looking at the result of the rest of the tests I did. I’ll definitely check the article and research deeper on all this.

I just had this same issue/question, and it would have been really nice if something like that was explained somewhere in any of the lessons.

Nowhere does it say anything like joops75’s line of

The only reason I was able to complete the challenge was from looking up the answer because of the same thing as bravas.

Moving forward from here, it will help me to remember that the lookaheads are “this first, all the way through, AND that, starting over, all the way through again” rather than “this and THEN that starting from where this left off”.

would you like to open a github issue about this?

Thank you for helping make FCC better. Bugs can be reported as GitHub Issues. Whenever reporting a bug, please check first that there isn’t already an issue for it and provide as much detail as possible.

Can I know what does \D*\d mean?

"0 or more non numbers followed by one number "

2 Likes