Positive and Negative Lookahead

Hi, I’m doing the “Positive and Negative Lookahead” challange and I really don’t get lookarounds when they are strung together. In the first example it presents us with:

let quit = "qu";
let noquit = "qt";
let quRegex= /q(?=u)/;
let qRegex = /q(?!u)/;
quit.match(quRegex);
noquit.match(qRegex);

Which is straightforward, it checks if there is a ‘q’ followed (or not followed) by ‘u’, but the second example isn’t clear

let password = "abc123";
let checkPass = /(?=\w{3,6})(?=\D*\d)/;
checkPass.test(password);

First lookahead is preceded by nothing, does it nean that it checks if there are 6 consecutive alfanumeric characters after:

  • beginning,
  • some kind of null special character,
  • or at any point in the string?

How do the lookarounds work together? Does the second lookaround check if there are two characters “\D\d” after those six characters from the first lookaround or does it work independently?

hi there, can you post a link to the challenge/topic you are reading?

my understanding of this is that the lookahead uses “the current position in the string” to “look ahead”.
That is, if it is examining the character at index 0 to begin with then it will try to lookahead from there to the first grouping (?=\w{3,6}) then if is finding a match (whether starting at index 0 or at a later point in the string), it will use that new point to begin the match for the second lookahead.

So they do work together because the first match advances the position in the string for the 2nd lookahead to use.

Have you considered using a site like regex101.com to help your understanding of the pattern? (you can paste the pattern into it, switch the matching option to ECMAScript then put some test strings so you can see how it performs the matching)

Thank you for recommending regex101, didn’t know something like that existed.

I’ve played around with it and I think it works a little bit different.

That is, if it is examining the character at index 0 to begin with then it will try to lookahead from there to the first grouping (?=\w{3,6}) then if is finding a match (whether starting at index 0 or at a later point in the string), it will use that new point to begin the match for the second lookahead.

I think that it starts at index 0, lookaheads to chack if there are 6 alfanumeric characters following index 0. Then it uses the same index 0 to lookahead if there are two digits following it.

The solution for that challange " Use lookaheads in the pwRegex to match passwords that are greater than 5 characters long, and have two consecutive digits." is:

let sampleWord = "astronaut";
let pwRegex = /(?=\w{6,})(?=\w*\d{2})/; // Change this line
let result = pwRegex.test(sampleWord);

It checks at index 0 if there are 6 or more alfanumeric characters and then it checks from index 0 if there are 0 or more alfanumeric characters followed by 2 digits. Then it moves to index 1 and so on…
But if instead you use:

let pwRegex = /(?=\w{6,})(?=\d{2})/;

It checks if there are 6 alfanumeric characters from index 0, then it checks if there are 2 digits following index 0, so if we were testing that conditions:

  • 11password would return true,
  • pa11ssword would return true,
  • passwo11rd would return false,
  • password11 would return false.

The last two would return false because when we check both lookaheads from the same index by the time we find two digits consecutively there aren’t 4 more characters following them to fullfill the 6 characters criterium from first lookahead.

Have I missed a nuance in your post but to me it sounds like you just confirmed that they do work together? The second one starts it’s match where the first ends?

Ps. Still waiting on you to post a link to the challenge.

Here is the link:

Now that I’ve typed it all out I realize that I said almost the same thing you did but in a much more roundabout way. One difference I can see is that in your explanation the second lookahead is applied only when the first one is matched which seems to make more sense then what I said, so that’s probably how it actually works.

Thank you for help

According to regex101 the look ahead pattern matches “without consuming”. So that’s probably why both patterns start looking for a match from index 0. (So I was not correct about the first one advancing the index).

Oh, I think that was my initial interpretation of your post. It seemed to me that in the initial example:

/(?=\w{3,6})(?=\D*\d)/;

you suggested starting at index 0, checking for 3-6 alfanumeric characters advancing the index to position 2-5 . Let’s say we 've found 4 alfanumeric characters, so we skip past indices [0, 1, 2, 3] and we look for \D*\d from index 4 onward.

In my post agreeing to

Have I missed a nuance in your post but to me it sounds like you just confirmed that they do work together? The second one starts it’s match where the first ends?

I’ve misunderstood it as “The second lookaround starts it’s match after the first one already confirms its own match”, because if the first lookahead returns false from let’ s say index 3, there is no point checking for the second lookahead. Thus they work together.

I am fairly sure based on the link to the exercise and the regex101 comment that both lookaheads are working “in tandem”. At the same time I read elsewhere that if you write a pattern to the left of a look ahead pattern such as the ones above, then the left pattern (in this case the first look ahead) will only “match” if the second pattern (in this case the second look ahead) matches too.
So they work “in tandem” or “in cooperation” but I was wrong to believe the left hand side pattern advances the index where the right hand side pattern applies.