如何构建特定的Java regexp

时间:2016-06-03 13:38:23

标签: java regex

我需要检查登录名。它必须(它是政治的,而不是技术决定):

  1. 5到30个字符;
  2. 字符必须来自群组[a-zA-Z0-9*];
  3. 至少一个字符必须是数字;
  4. 如果登录名有5个字符,但是如果它有6个或更多字符,则不可能只使用数字中的所有字符,只能用数字构建它。
  5. 我有正则表达式(?=[a-zA-Z0-9*]*[0-9])[a-zA-Z0-9*]{5,30}适用于第1-3点,但无法想象如何包含第4点的检查。

4 个答案:

答案 0 :(得分:1)

将正则表达式与negative look ahead assertion

一起使用
(?!\d{5}$)(?=[a-zA-Z\d*]*\d)[a-zA-Z\d*]{5,30}

Regex explanation here.

Regular expression visualization

答案 1 :(得分:1)

使用单个非常复杂的正则表达式来验证字符串的所有方面总是很诱人。但请记住,这件事可能难以扩展,并在将来维持。

含义:取决于"变化率"根据验证规则,可能会有更好的设计。例如,人们可以想象:

interface NameValidator {
    isValid(String name) throws InvalidNameException;
}

class LengthValidator implements NameValidator ...
class XyzValidator implements NameValidator ...

class NameValidation {
   private final List validators = Arrays.toList(new LengthValidator(), ...

   void isValid(String name) {
      run all validators ...

这样,添加/更改一个验证规则......变得更加直接......而不是篡改单个正则表达式,可能会破坏其中的其他部分。

除此之外,你甚至可以建立不同的规则集;通过组合NameValidation实现者的不同实例;同时避免代码重复。

答案 2 :(得分:0)

正如其他人所指出的那样,你不需要用一个正则表达式来做。即使这是可能的,也会令人讨厌地复杂且难以理解。

最简单的方法是最好的:

boolean passwordValid = password.matches("[a-zA-Z0-9*]{5,30}")
    && password.matches(".*[0-9].*")
    && !password.matches("[0-9]{5}");

答案 3 :(得分:0)

我想提出一种不同的方法:不要使用正则表达式,但要检查每个字符并收集密码属性。这样,您就可以在以后实施更复杂的要求,例如: "它必须有4个中的3个"。

示例:

String pw = "1a!cde";

Set<PwProperty> passwordProperties = new HashSet<>();
for( char c : pw.toCharArray() ) {
  if( isDigit( c ) ) { 
    passwordProperties.add( PwProperty.DIGIT ); 
  }
  else if ( isSpecialChar( c ) ) { 
    passwordProperties.add( PwProperty.SPECIAL); 
  }
  else if( isUpperCase( c ) ) {
    passwordProperties.add( PwProperty.UPPER_CASE); 
  }
  else if( isLowerCase( c ) ) {
    passwordProperties.add( PwProperty.LOWER_CASE); 
  }
  else {
    passwordProperties.add( PwProperty.UNKNOWN ); 
  }
}

然后你可以像这样检查(伪代码):

if( !pw.length() in range ) {
   display "password too short" or "password too long"
}

if( passwordProperties.contains( PwProperty.UNKNOWN ) {
  display "unsupported characters used"
}

Set<PwProperty> setOf4 = { DIGIT, SPECIAL, LOWER_CASE, UPPER_CASE }
if( intersection( passwordProperties, setOf4 ).size() < 3 ) {
  display "use at least 3 out of 4"
}

if( !passwordProperties.contains( DIGIT ) ) {
  display "must contain digits"
}

display "password strength" being intersection( passwordProperties, setOfGoodProperties ).size()

etc.

然后可以扩展,例如像DIGIT_SEQUENCE这样的属性可能是不需要的等等。

主要优点是你有更详细的密码信息,而不是&#34;它与某个正则表达式匹配与否#34;并且您可以使用该信息来指导用户。