我需要验证一个输入字符串,这样只有当字符串包含一个特殊字符@#$%,只有一个,最多一次时,验证才返回true
。字母和数字可以在任何地方,可以重复任意次数,但至少应有一个数字或字母
例如:
a @:true
@a:true
@ $:false
a @ n01:true
an01:false
a:false
@:false
我试过
[0-9A-Za-z]*[@#%$]{1}[0-9A-Za-z]*
我希望这会匹配任何特殊字符的一次出现。但不是。我只需要在集合中出现任何一个。
我也尝试过轮换,但无法解决。
答案 0 :(得分:13)
Vivek,你的正则表达式非常接近。这是您正在寻找的单行正则表达式。
^(?=.*?[0-9a-zA-Z])[0-9a-zA-Z]*[@#$%][0-9a-zA-Z]*$
请参阅demo
它是如何运作的?
^
和$
锚点确保我们匹配的是整个字符串,以避免以后与禁用字符部分匹配。(?=.*?[0-9a-zA-Z])
前瞻确保我们至少有一个数字或字母。[0-9a-zA-Z]*[@#$%][0-9a-zA-Z]*
匹配零个或多个字母或数字,后跟完全一个字符@
,#
,$
或%
,后跟零个或多个字母或数字 - 确保我们有一个特殊字符但不能再有。<强>实施强>
我相信你知道如何在Java中实现它,但是为了测试字符串是否匹配,你可以使用这样的东西:
boolean foundMatch = subjectString.matches("^(?=[0-9a-zA-Z]*[@#$%][0-9a-zA-Z]*$)[@#$%0-9a-zA-Z]*");
我的正则表达式出了什么问题?
实际上,你的正则表达式几乎就在那里。这是缺少的。
^
和$
锚点,因此正则表达式能够匹配字符串的子集,例如a#
中的a##%%
,意味着特殊字符可以出现在字符串中,但在匹配之外。不是你想要的:我们需要通过锚定来验证整个字符串。替代变更
由于你尝试过替换,为了记录,这是一种方法:
^(?:[0-9a-zA-Z]+[@#$%][0-9a-zA-Z]*|[0-9a-zA-Z]*[@#$%][0-9a-zA-Z]+)$
请参阅demo。
如果您有任何问题,请与我们联系。
答案 1 :(得分:1)
我希望这个答案对你有用,如果没有,它可能是为了未来的读者。我将在前面做两个假设:1)你不需要正则表达式,你用Java编程。 2)您可以访问Java 8。
这可以通过以下方式完成:
private boolean stringMatchesChars(final String str, final List<Character> characters) {
return (str.chars()
.filter(ch -> characters.contains((char)ch))
.count() == 1);
}
我在这里:
String
和List<Character>
个允许的内容作为输入。IntStream
获取String
(由字符组成)。char
,只有在List<Character>
中才会保留在流中。true
(count() == 1
中的字符,只有一个存在时)才会返回List<Character>
。代码可以用作:
String str1 = "a";
String str2 = "a@";
String str3 = "a@@a";
String str4 = "a#@a";
List<Character> characters = Arrays.asList('@', '#', '$', '%');
System.out.println("stringMatchesChars(str1, characters) = " + stringMatchesChars(str1, characters));
System.out.println("stringMatchesChars(str2, characters) = " + stringMatchesChars(str2, characters));
System.out.println("stringMatchesChars(str3, characters) = " + stringMatchesChars(str3, characters));
System.out.println("stringMatchesChars(str4, characters) = " + stringMatchesChars(str4, characters));
导致false
,true
,false
,false
。