Regex lookaheads, more explanation if possible

Can you explain to me this part of the lesson:
A more practical use of lookaheads is to check two or more patterns in one string. Here is a (naively) simple password checker that looks for between 3 and 6 characters and at least one number:

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

Hi @bedward!

What part of the lesson is giving you trouble specifically? The more information you can provide us on what parts of the regular expression are confusing the better we can help.

Also, there is a great resource called regex 101 where it will test your regular expressions and provide explanations on what each part does. Just make sure to pick the right language before inputting your regex for testing.

2 Likes

There are two things in regexp you need to consider:

  1. Character
  2. Cursor

Just like in any text editor cursor might be positioned just before the character or just after - never on the character itself. If cursor progresses forward it “eats” character checking the pattern.

Look aheads are instructions that tell regexp (cursor) to “look ahead” from it’s current position (index). So two instructions provided in your example can be translated in English like so:

  1. Without eating characters, look ahead and see if there are from 3 to 6 alphanumeric characters \w
  2. Without eating characters, look ahead and see if there is any digit \d followed by 0 or more non-digit characters.

Note that there is no specification of any particular position of these :point_up: characters or digits, which makes this rule very loose.

1 Like

And in the example of "abc123" does the lookaheads both scan the string?
for example: does (?=\w{3,6}) scans the whole "abc123", and then (?=\D*\d) comes after and re-scans the "abc123", for checkPass to return true?

1 Like

yes, they both check the string, also they look from the same position

1 Like

What wrong with that? :

let password = "abc11bfaa";
let checkPass = /(?=\w{3,6})(?=\D*\d\d)/;
let result = checkPass.test(password); // Returns true
console.log(result);

The above ‘(naively) simple password checker’ is supposed to look for between 3 and 6 characters and at least one number, but it does return true for “abc11bfaa” although it is more than 6 characters long, is the problem in the code or i didn’t understand well, can someone clarify please?

as it is, it returns true because the string contains a substring that match the pattern.

To make it match the string exactly you need to put in also the start of string and/or the end of string anchors (^ and $)

Does the /(?=\w{3,6})(?=\D*\d\d)/ work like /(?=\w{3,6})OR(?=\D*\d\d)/ i mean that if only one of them is true (i.e. (?=\w{3,6}) or (?=\D*\d\d)) the whole regex (/(?=\w{3,6})(?=\D*\d\d)/) tests true?

no, both patterns need to match

and if ‘both patterns need to match’ why "abc11bfaa" tests true although it is 6+ characters?

yes, they are both true, because the string contains a substring that satisfy the pattern

/a/.test("banana") returns true because the string contains an “a”

you need to use the anchors to have a pattern for the whole string

This one --> "a bc 123" also tests true, where is the sub-string that satisfies the pattern?

you can always test your code with something like https://regex101.com/

the substring is “123”

1 Like

-_-, i was asking why tests true not how to test a new code, if you have no idea why you can say that.

if you use that, you can try with all the strings you want. The substring is “123”

see, it has matched the position before the 1:
image

You need to chill a bit. The only person who has no idea so far is you

Do you think that your comment was necessary? I wasn’t even addressing that to you…

Now, replying to your question, 123 are 3 alphanumeric characters, therefore they selected by \w{3,6} rule.

This is an awesome resource, thanks!

1 Like