我正在改进密码,客户想要一个没有连续字母的密码,即:123、234。
我发现您可以在正则表达式中声明要匹配的字符串,(012|123|234|345|456|567|678|789|890)
并将其作为正则表达式序列。
该序列与其他序列分开以便于阅读。
问题是,即使我在密码字符中包含 123 或 234,我也无法将密码与模式匹配。
我读过正则表达式无法将 123 检测为连续数字,但作为字符串,它可以这样做吗?
如果您只处理 要排除的这些数字字符串,则可以使用否定的前瞻断言来实现:
^(?!.*(012|123|234|345|456|567|678|789|890))<regex>
<regex>
您用于匹配密码的实际正则表达式在哪里,并且(?!...)
是断言不可能在您的正则表达式中匹配该字符串的前瞻。
如果您要询问任何增加的字符序列,那么正则表达式不是解决此问题的正确工具。您必须以编程方式执行此操作。
如果您的字符序列有限,则可以在输入的匹配器上使用Pattern
,并反转测试:.find()
// Only the alternation is needed, no need for the capture
private static final Pattern PATTERN
= Pattern.compile("012|123|234|345|456|567|678|789|890");
// ...
if (PATTERN.matcher(input).find())
// fail: illegal sequence found
但是,如果您想检测代码点彼此跟随,则必须使用字符函数:
final CharBuffer buf = CharBuffer.wrap(input);
int maxSuccessive = 0;
int successive = 0;
char prev = buf.get();
char next;
while (buf.hasRemaining()) {
next = buf.get();
if (next - prev == 1)
successive++;
else {
maxSuccessive = Math.max(maxSuccessive, successive);
successive = 0;
}
prev = next;
}
// test maxSuccessive
但是请注意,这将根据“规范排序”而不是排序规则来测试连续的字符。例如,在某些语言环境中,紧随其后a
的是A
,而不是b
。
更一般地说,如果你想测试密码要求和约束的演变,你最好把事情分开一点。例如,考虑一下:
public interface PasswordChecker
{
boolean isValid(final String passwd);
}
为你的每一个检查实现这个接口(例如,长度、某些字符的存在/不存在等),当你检查密码时,有一个List
检查器;如果一个检查器返回 false,则密码无效:
private final List<PasswordChecker> checkers = ...;
// then
for (final PasswordChecker checker: checkers)
if (!checker.isValid(passwd))
return false;
return true;
如果你使用 Guava,你可以忘记PasswordChecker
并使用Predicate<String>
.