7

How would I get this so it would check for 2 or more digits in the String? Invoking matches on the String s.

s.matches("^[a-zA-Z0-9]{8,}$");
6
  • 2
    To check for a digit in Java, you have to use \p{Nd}. If you just want [0-9], that’s different of course. Commented Feb 17, 2011 at 0:01
  • Do you have some sample input? Commented Feb 17, 2011 at 0:05
  • @tchrist I find it entertaining that you correct this error in almost every regex question :) (not complaining -- I didn't realise the difference before you noted it) Commented Feb 17, 2011 at 0:14
  • @Tim what's the difference btw? Commented Feb 17, 2011 at 0:17
  • @OscarRyz \p{Nd} contains another 410 characters, including the Soviet U+0968 (२). Commented Feb 17, 2011 at 0:19

6 Answers 6

8

This should do it...

^(?=.*[0-9].*[0-9])[a-zA-Z0-9]{8,}$

The only change I made is adding this (?=.*[0-9].*[0-9]) which is a positive lookahead that will try to find the first 2 digits within the password. If it's satisfied, then the regular expression will proceed as usual.

Now, I just thought I'd point out that your regular expression will disallow special characters (punctuation and such). In practice, some people like to enter weird characters like this in their passwords.

So you might consider something more like this...

^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9]).{8,}$

This will allow special characters while also ensuring at least one capital letter, one lower case letter, and one number exist in the password. This is just an example of a strong password regular expression I wrote awhile back, and you could certainly relax those restrictions a bit if you so desired.

Sign up to request clarification or add additional context in comments.

1 Comment

+1: It's just amazing how complicated this doesn't have to be!
1

Match it twice:

s.matches("^[a-zA-Z0-9]{8,}$");
s.matches("[0-9].*[0-9]");

Use the results like this:

if ( s.matches("^[a-zA-Z0-9]{8,}$") && s.matches("[0-9].*[0-9]") ) {
    # password is valid
}

18 Comments

Does not work. return s.matches("^[a-zA-Z0-9]{8,}$") && s.matches("[0-9].*[0.9]"); returns false for "2aaaaa2". It should check if theres 2 or more digits aswell as minimum 8 length string.
What does not work? You will have to use the return values for those two statements.
@unleashed: The first one checks for the minimum length. It returns false for "2aaaaa2" because it contains 7 characters, and 7<8.
@spintheblack: No. The ^ and $ metacharacters are used to match start and end of a string. The second regex lacks them.
@Skurmedel Java's regex implementation is slightly different because the match method doesn't consume all the input. So \d.*\d doesn't "matches" a2aa2a ( returns false ) but using find() does work.
|
1

Try this: (?:^|\s+)(\w{8,})(?<=(.*\d.*\d.*))(?:\s+|$)

Modified to allow for more than 8 chars from: http://social.msdn.microsoft.com/Forums/en/regexp/thread/8e0ced1f-8ddc-4583-89de-e29b4c4dc726

2 Comments

+1 @Tim, i was going to mention that in the answer but didn't want to sound like a n00b. Now the answer looks hardcore!! yeah! (as long as it works)
"Hardcore" isn't the word I would use. :D And no, it doesn't work. .NET is one of only two regex flavors that support unbounded variable-length lookbehind, and the other one is not Java; that check should be done in a lookahead. And why would you check for even one whitespace character at either end, much less one or more? Even the anchors aren't necessary in this case, because the OP is using the matches() method, which implicitly anchors the match at both ends.
1

I really don't see any good reason to check the length of a string with a regex - keep it simple is always a good idea, but especially with regexes the temptation to throw everything into a completely unreadable string (that may have some strange edgecases) is pretty tempting.

Just use the length method for the length and something like "\w*?\d\w*?\d\w*" Note that .* is greedy so don't forget the ? after it. \d signifies a digit in java - I don't think there are any cases with unicode you'd miss with [0-9] - but better safe than sorry

Edited to use \w instead of . (only word characters i.e. [a-zA-Z_0-9])

1 Comment

That regex does not find if the string contains only alphanumeric characters and at least two digits? Agree with you on length check, though.
1

How about this?

private Pattern p1  = Pattern.compile("^\\w{8,}$");
private Pattern p2  = Pattern.compile("\\d+(.*)?\\d+");

private boolean match(String s) {
    return p1.matcher(s).find() && p2.matcher(s).find();
}

@Test
public void testPassword() {
    assertTrue("length at least 8", match("2aaaaaa2"));
    assertTrue("length at least 8", match("aaaaaaa22"));
    assertTrue("length at least 8", match("22aaaaaaa"));
    assertTrue("length at least 8", match("aa2aa2aaa"));

    assertFalse("length less than 8", match("2aa2aaa"));
    assertFalse("one digit", match("aa2aaaaa"));
    assertFalse("no digits", match("aaaaaaaa"));
}

1 Comment

(.*)?? You're cruisin' for a Resonance Cascade Scenario there, dude. Er, I mean catastrophic backtracking, of course! (regular-expressions.info/catastrophic.html)
1

edit

Don't use match, but find. ( read the documentation )

The matches method attempts to match the entire input sequence against the pattern.>

That's why \d.*\d doesn't work with a2a2a

The find method scans the input sequence looking for the next subsequence that matches the pattern.

This is what you need.

You just have to test if there is are two numbers with anything in between \d.*\d :

import java.util.regex.*;
class TwoDigits { 
    public static void main( String ... args ) { 
        Pattern pattern = Pattern.compile("\\d.*\\d");
        Matcher matcher = pattern.matcher( args[0]  );  
        System.out.println("Matched ( found ) ? = " + matcher.find());
    }
}

But perhaps I'm missing something here, why don't your try it and tell us where it fails.

C:\java>java TwoDigits ""
Matched ( found ) ? = false

C:\java>java TwoDigits "a"
Matched ( found ) ? = false

C:\java>java TwoDigits "1a1"
Matched ( found ) ? = true

C:\java>java TwoDigits "1a"
Matched ( found ) ? = false

C:\java>java TwoDigits "a1a"
Matched ( found ) ? = false

C:\java>java TwoDigits "a1a1"
Matched ( found ) ? = true

C:\java>java TwoDigits "2a2"
Matched ( found ) ? = true

C:\java>java TwoDigits "2aaa2"
Matched ( found ) ? = true

C:\java>java TwoDigits "2aaaaaaaaaaaaaaa2"
Matched ( found ) ? = true

C:\java>java TwoDigits "2aaaaaaaaaaaaaaa"
Matched ( found ) ? = false

C:\java>java TwoDigits "2aaaaaa2aaaaaaaaaa"
Matched ( found ) ? = true

C:\java>java TwoDigits "a3aaaaa2aaaaaaaaaa"
Matched ( found ) ? = true

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.