1

I am building a password checker - I have a simple requirement for at least three lowercase non-consecutive letters for now and either I have a large misunderstanding of regexes, or something else.

I have written the following code:

var password = 'mYpAsSwOrD',
    r = new RegExp('[a-z]{3,}', 'g');

console.log(password.match(r)); // null
console.log(r.test(password)); // false

Also, is the 'g' flag needed? Does the quantifier not provide the same functionality effectively?

What is the better comparison? Matching the regex against the string (first example); or testing the string against the regex (second example)?

6
  • 1
    requirement for at least three lowercase letters. Can you please explain this part more? Commented Oct 6, 2014 at 11:15
  • [a-z]{3,} will not match capitol letter or numbers os specail characters.Is this a requirement? Commented Oct 6, 2014 at 11:16
  • 2
    your current regex is currently checking for at least 3 consecutive lowercase letters. Commented Oct 6, 2014 at 11:16
  • Thanks Jerry - any idea how I can enhance it so it looks for three characters, non-consecutive? Commented Oct 6, 2014 at 11:17
  • @keldar Maybe easiest way would be to replace all characters that are not lowercase letters and get the string length of the resulting string. Commented Oct 6, 2014 at 11:20

3 Answers 3

2

It matches only the strings which has atleast 3 lowercase letters.

> /^(?:[^a-z]*[a-z]){3}/.test("mYpAsSwOrD")
true

Explanation:

  • ^ Asserts that we are at the start.
  • (?..) Called non-capturing groups, which won't capture any characters but would do only matching operation.
  • [^a-z]* this would match any character zero or more times.
  • [a-z] this would match a lowercase letter.
  • (?:[^a-z]*[a-z]){3} So if the whole non-capturing group is repeated three times, it could match the strings with atleast three lowercase letters. For testing purposes only , we don't need to go for a full match.

OR

You could try the below positive lookahead.

^(?=(?:[^a-z]*[a-z]){3})

Code:

> /^(?=(?:[^a-z]*[a-z]){3})/.test("mYpAsSwOrD")
true
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks - could you expand on how this works a little? Particularly, the '?:' syntax?
@Jonny5 yep the first one take 13 steps to finish whether the second lookahead takes 15 steps to finish.
1
(?=(.*?[a-z]){3}).*

You can try this.See demo.

http://regex101.com/r/hQ1rP0/24

4 Comments

Awesome! Thank you. Could you explain/expand your answer just to describe the syntax - I haven't come across the ?= syntax before
@keldar it called positive lookahead.it looks for the condition of 3 small letters ahead.
Oh yeah, makes sense now :) - I don't think '.*' is needed at the end, because of the positive lookahead provides the same functionality (or have I misunderstood).
@keldar .* is needed to consume the strings...... lookahead does not consume string
0

Your original regex matches where the three desired characters are consecutive. You can change the regex to this:

r = /[a-z](?:[^a-z]*[a-z]){2}/;
  • [a-z] Matches a lowercase character.
  • (?:[^a-z]*[a-z]) Skips over all non-lowercase characters and attempts to match a lowercase character.
    • {2} Two times.

As for your other question, the g flag is not necessary as it allows repeat matches, while for your use case you're simply matching the first collection and asserting true for return.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.