正则表达式不按预期工作

时间:2012-05-11 18:06:03

标签: java regex

我正在使用以下正则表达式。 (?= + [A-Z])(?= + [A-Z])(?= + [^ A-ZA-Z])。{8,}

我的目标是拥有一个密码,其中包含以下4个属性中的3个

大写字符,小写字符,数字,特殊字符

我正在使用http://rubular.com/r/i26nwsTcaUhttp://regexlib.com/RETester.aspx来测试带有以下输入的表达式

P@55w0rd
password1P
Password1
paSSw0rd

所有这些都应该通过,但只有第二个和第四个在http://rubular.com/r/i26nwsTcaU传递,所有这些都在http://regexlib.com/RETester.aspx传递。

我还有以下用于验证的代码

private void doValidate(String inputStr,String regex) {
    Pattern pattern = Pattern.compile(regex);
    if(!pattern.matcher(inputStr).matches()){
        String errMessage = "";
        throw new UniquenessConstraintViolatedException(errMessage);
    }
}

此代码无法验证应传递的“Password1”。 就表达而言,我理解为这样

must have lower (?=.+[a-z])
must have upper (?=.+[A-Z])
must have non alpha (?=.+[^a-zA-Z])
must be eight characters long .{8,}

任何人都可以告诉我这是错的。

提前致谢。

4 个答案:

答案 0 :(得分:1)

基本上,.+子表达式应该归咎于它们,它们应该是.*。否则,前瞻部分会查找小写,大写或非字母,但每个相应类型的字符如果是字符串中的第一个字符则不计算。因此,您要验证的不是密码,而是验证第一个char被截断的密码。虽然@Cfreak不对,但他很接近 - 正常的正则表达式无法实现你正在做的事情,你必须使用他的建议。使用lookahead群组 - (?=) - 可以满足您的需求。不过,我个人更愿意像@Cfreak建议的那样编码它 - 它更具可读性,你的意图从代码中更清晰。复杂的正则表达式往往难以编写,但在一段时间后几乎无法读取,调试或改进。

答案 1 :(得分:0)

你的正则表达式现在说你必须有一个或多个小写字符,后跟一个或多个大写字符后跟一个或多个大写或小写字符,后跟8个字符或更多字符。

除非您指定特定字符的出现位置,否则正则表达式不能执行AND。你基本上需要将你的正则表达式的每个部分分成它自己的正则表达式并检查每个部分。您可以使用Java具有的任何字符串长度方法来检查长度(抱歉,我不是Java开发人员,因此我不知道它是什么。)

伪代码:

if( regexForLower && regexForUpper && regexForSpecial && string.length == 8 ) {
     // pass
}

答案 2 :(得分:0)

正如我在评论中所说,位置0大写字母被忽略。

这是所有四个密码都匹配的正则表达式。

(?=.+\\d)(?=.+[a-z])(?=\\w*[A-Z]).{8,}

答案 3 :(得分:0)

我不会使用这样的正则表达式。

  • 很难理解
  • 难以调试
  • 难以延伸
  • 你的结果不能做多少

如果您想告诉客户端密码有什么问题,您可以再次调查密码。在现实环境中,您可能希望支持来自外部语言环境的字符。

import java.util.*;
/**
    Pwtest

    @author Stefan Wagner
    @date Fr 11. Mai 20:55:38 CEST 2012
*/
public class Pwtest
{

    public int boolcount (boolean [] arr) {
        int sum = 0;
        for (boolean b : arr) 
            if (b) 
                ++sum;
        return sum;
    }

    public boolean [] rulesMatch (String [] groups, String password) {
        int idx = 0;
        boolean [] matches = new boolean [groups.length];
        for (String g: groups) {
            matches[idx] = (password.matches (".*" + g + ".*"));
            ++idx;
        }
        return matches;     
    }

    public Pwtest ()
    {
        String [] groups = new String [] {"[a-z]", "[A-Z]", "[0-9]", "[^a-zA-Z0-9]"};
        String [] pwl = new String [] {"P@55w0rd", "password1P", "Password1", "paSSw0rd", "onlylower", "ONLYUPPER", "1234", ",:?!"};
        List <boolean[]> lii = new ArrayList <boolean[]> ();
        for (String password: pwl) {
            lii.add (rulesMatch (groups, password)); 
        }

        for (int i = 0 ; i < lii.size (); ++i) {
            boolean [] matches = lii.get (i); 
            String pw = pwl[i];
            if (boolcount (matches) < 3) {
                System.out.print ("Password:\t" + pw + " violates rule (s): ");
                int idx = 0; 
                for (boolean b: matches) {
                    if (! b) 
                        System.out.print (groups[idx] + " "); 
                    ++idx;
                }
                System.out.println (); 
            }
            else System.out.println ("Password:\t" + pw + " fine ");
        }
    }

    public static void main (String args[])
    {
        new Pwtest ();
    }
}

输出:

Password:   P@55w0rd fine 
Password:   password1P fine 
Password:   Password1 fine 
Password:   paSSw0rd fine 
Password:   onlylower violates rule (s): [A-Z] [0-9] [^a-zA-Z0-9] 
Password:   ONLYUPPER violates rule (s): [a-z] [0-9] [^a-zA-Z0-9] 
Password:   1234 violates rule (s): [a-z] [A-Z] [^a-zA-Z0-9] 
Password:   ,:?! violates rule (s): [a-z] [A-Z] [0-9] 
Password:   Übergrößen345 fine 
Password:   345ÄÜö violates rule (s): [a-z] [A-Z]