Hello fellow campers, first-time poster here! (so apologies in advance if I fail to comply with any forum guidelines).
Even though I’ve progressed 4 courses further down the line, I recently came back to the RegEx course to take notes and fidget with the code to see what else I could do with it and to really make sure I understand how it works. Turns out, I don’t. I can get it to work, but doing so without really understanding what’s going on under the hood is less than ideal. Given the things I understand (or think I understand) about lookaheads, I can’t make sense of some things about the exercise and other tests I’ve ran. I’ve tried lots of things, read through a few forum posts, and also read the Lookahead and lookbehind page, but I’m still missing something. So I’m going to list the premises I’ve gathered about how I think lookaheads work, explain what isn’t making sense for me, and hopefully someone will be able to correct what’s wrong about my assumptions, or provide the piece of the puzzle I’m missing. I’ll try to make it not excessively boring.
Premise 1:
Lookaheads check to see if a pattern is present anywhere in a string.
Premise 2:
Because lookaheads check to see if a pattern is present anywhere in a string, the order of the lookaheads (if there’s more than one) doesn’t matter. i.e. / ( ? = \w{3} ) ( ?= \d ) / should work the same as / ( ?= \d ) ( ? = \w{3} ) / .
(the order does matter, however, if there’s a part of the RegEx before the lookahead. E.g.: / q(?=u) / will only match if there’s a letter “u” immediately after the letter “q”.
Premise 3:
Lookaheads don’t put limits on the amount of characters a string must have. For example, a lookahead that looks for a pattern of three consecutive letters will match a three-letter string, but it will also match longer strings.
E.g.: regex = /( ? = \w{3} ) / will return true for “abc”, but it will also return true for “abcd”, “abcde”, and so on.
Because of this, I don’t understand why the exercise says that the code for a password checker that “looks for between 3 and 6 characters” is / ( ?=\w{3,6} ) /. It stands to reason that it’s telling us to make sure the password is not over 6 characters long, but this code doesn’t limit the length of the string; as long as there’s at least three consecutive alphanumeric characters, it will match strings of any length over that. Also, adding “,6” does nothing.
Also, because of Premise 1, I don’t understand why the \D* is necessary in the example given:
let password = “abc123”;
let checkPass = /(?=\w{3,6})(?=\D*\d)/;
If the lookahead checks to see if something is present anywhere in the string, \d should be enough, as it’s telling the computer to see if there’s at least one number anywhere in the string, not caring about what’s in the rest of the string. Even using \D* , it allows for the possibility of there being zero non-numbers before the number, so it feels like there’s no need for it.
I try different combinations, and some things happen which I can’t understand:
— If I take out the \D*:
let quit = “abc123”;
let quRegex = /(?=\w{3,6})(?=\d)/;
quRegex.test(quit)
returns true! Just like I though it would.
but if I change the quit variable to “abcd23” or “abcde3”:
let quit = “abcd23”;
let quRegex = /(?=\w{3,6})(?=\d)/;
quRegex.test(quit)
now it returns false , even though there’s still at least one number in the string. I have no idea why this happens.
I continue troubleshooting and see that, if I remove the first lookahead:
let quit = “abcd23”;
let quRegex = /(?=\d)/;
quRegex.test(quit)
It now returns true.
And if I change the first lookahead to /(?=\w{6}):
let quit = “abcd23”;
let quRegex = /(?=\w{6})(?=\d)/;
quRegex.test(quit)
This will only return true if there’s at least six numbers in the string.
So I’m guessing that… the number in the first lookahead is impacting on the second lookahead? How does that work? I thought they were supposed to be independent from each other. They both need to be true for the lookahead to return true, yes, but they look for different things. Or that’s what I thought. How do they really work? Also, in the last case, if I bring back the \D*, now it returns “true”, even if there’s less than 3 numbers, so I’m even more confused.
So yeah, lots of questions regarding how lookaheads work and the solutions provided for the exercises. I’ll sum 'em up below and hope I don’t forget any. Hopefully, someone will be able to explain to me what’s wrong about my premises, or what the heck is going on.
A) Why is it necessary to use / ( ?=\w{3,6} ) / when making sure a password is “between 3 and 6 characters” if this does not put a limit on the amount of characters and it only checks to see if there are at least 3 consecutive letters anywhere in the string?
B) Why is \D* necessary in the example given? (?=\d) should be enough to simply look for a number, and it did work.
C) Why does the first lookahead seem to be impacting on how the second lookahead behaves? And if that’s the case, how does this work?
Thank you to anyone who’s taken the time to read this admittedly-long post, and thanks in advance for any attempts at bringing some clarity to this.
Link to the challenge: