Java 正则表达式无法正常工作
我使用以下正则表达式。 (?=.+[a-z])(?=.+[a-z])(?=.+[^a-zA-z])。{8,} 我的目标是拥有一个具有以下4个属性中的3个属性的密码 大写字符、小写字符、数字、特殊字符 我正在使用and来测试带有以下输入的表达式Java 正则表达式无法正常工作,java,regex,Java,Regex,我使用以下正则表达式。 (?=.+[a-z])(?=.+[a-z])(?=.+[^a-zA-z])。{8,} 我的目标是拥有一个具有以下4个属性中的3个属性的密码 大写字符、小写字符、数字、特殊字符 我正在使用and来测试带有以下输入的表达式 P@55w0rd password1P Password1 paSSw0rd 所有这些都应该通过,但只有第二个和第四个在通过,而且所有这些都在通过 我还使用以下代码进行验证 private void doValidate(String inputStr,
P@55w0rd
password1P
Password1
paSSw0rd
所有这些都应该通过,但只有第二个和第四个在通过,而且所有这些都在通过
我还使用以下代码进行验证
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,}
谁能告诉我我做错了什么
提前感谢。您的正则表达式现在说您必须有1个或多个小写字符,后跟1个或多个大写字符,后跟1个或多个大写或小写字符,后跟8个或更多字符 正则表达式不能执行和,除非指定特定字符的显示位置。您基本上需要将正则表达式的每个部分拆分为自己的正则表达式,并检查每个正则表达式。您可以使用Java拥有的任何字符串长度方法来检查长度(很抱歉,我不是Java开发人员,所以我不知道它是什么) 伪代码:
if( regexForLower && regexForUpper && regexForSpecial && string.length == 8 ) {
// pass
}
正如我在评论中所说,第0位大写字母被忽略了 这是一个四个密码都匹配的正则表达式
(?=.+\\d)(?=.+[a-z])(?=\\w*[A-Z]).{8,}
本质上,应该归咎于
+
子表达式,它们应该是*
。否则,先行部分将查找小写、大写或非alpha,但如果每个对应类型的字符是字符串中的第一个字符,则该字符不计算在内。因此,您验证的不是密码,而是第一个字符被截断的密码。虽然@Cfreak是不对的,但他很接近——你所做的事情在普通正则表达式中是不可能的,你必须使用他的建议。使用组-(?=)
-可以执行您需要的操作。不过,就我个人而言,我更愿意像@Cfreak所建议的那样编写代码——代码更可读,您的意图也更清晰。复杂的正则表达式往往很难编写,但经过一段时间后几乎无法读取、调试或改进。我不会使用这样的正则表达式
- 这很难理解
- 难以调试
- 难以扩展
- 你对它的结果无能为力
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 ();
}
}
@Vulcan,但或将意味着它将匹配所有这些。问题是你的首字母大写字母被忽略了。如果在字符串中的任何其他位置添加大写字母,则密码1和密码3都可以使用。数字检查在哪里?(?=.+[^a-zA-Z])这会查找任何非字母字符,因此数字或特殊字符不必。我现在有了一个模式,除了第一个,它可以接受所有的模式,但这是因为@符号。谢谢大家的快速回复。解决了我的问题。我之所以使用正则表达式将密码规则外部化,以便以后可以在不重新部署应用程序的情况下对其进行更改。再次感谢所有的回复。
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]