我有以下字符,我希望被视为“非法”:
~
,#
,@
,*
,+
,%
,{
,}
,<
,>
,[
,]
,|
,“
,”
,\
,{ {1}},_
我想编写一个检查字符串并确定(^
/ true
)的方法,如果该字符串包含这些非法行为:
false
但是,对此进行简单的public boolean containsIllegals(String toExamine) {
return toExamine.matches("^.*[~#@*+%{}<>[]|\"\\_^].*$");
}
检查是不可行的。我需要方法来扫描字符串中的每个字符,并确保它不是这些字符之一。当然,我可以做一些可怕的之类的事情:
matches(...)
是否有更优雅/更有效的方法来实现这一目标?
答案 0 :(得分:27)
您可以在此处使用Pattern
和Matcher
课程。您可以将所有已过滤的字符放在字符类中,并使用Matcher#find()
方法检查您的模式是否以字符串形式提供。
你可以这样做: -
public boolean containsIllegals(String toExamine) {
Pattern pattern = Pattern.compile("[~#@*+%{}<>\\[\\]|\"\\_^]");
Matcher matcher = pattern.matcher(toExamine);
return matcher.find();
}
如果在字符串中找到给定的模式, find()
方法将返回true,甚至一次。
尚未指出的另一种方法是使用String#split(regex)
。我们可以在给定模式上拆分字符串,并检查数组的长度。如果length为1
,则模式不在字符串中。
public boolean containsIllegals(String toExamine) {
String[] arr = toExamine.split("[~#@*+%{}<>\\[\\]|\"\\_^]", 2);
return arr.length > 1;
}
如果arr.length > 1
,这意味着字符串包含模式中的一个字符,这就是它被拆分的原因。我已将limit = 2
作为第二个参数传递给split
,因为我们只需单次拆分即可。
答案 1 :(得分:11)
我需要方法来扫描字符串中的每个字符
如果你必须逐个字符地进行,那么regexp可能不是一个好方法。但是,由于“黑名单”中的所有字符都具有小于128的代码,因此您可以使用小boolean
数组执行此操作:
static final boolean blacklist[] = new boolean[128];
static {
// Unassigned elements of the array are set to false
blacklist[(int)'~'] = true;
blacklist[(int)'#'] = true;
blacklist[(int)'@'] = true;
blacklist[(int)'*'] = true;
blacklist[(int)'+'] = true;
...
}
static isBad(char ch) {
return (ch < 128) && blacklist[(int)ch];
}
答案 2 :(得分:8)
如果你不能使用匹配器,那么你可以做这样的事情,它比一堆不同的if语句或字节数组更清晰。
for(int i = 0; i < toExamine.length(); i++) {
char c = toExamine.charAt(i);
if("~#@*+%{}<>[]|\"_^".contains(c)){
return true;
}
}
答案 3 :(得分:8)
使用常量来避免在每次验证中重新编译正则表达式。
private static final Pattern INVALID_CHARS_PATTERN =
Pattern.compile("^.*[~#@*+%{}<>\\[\\]|\"\\_].*$");
并将您的代码更改为:
public boolean containsIllegals(String toExamine) {
return INVALID_CHARS_PATTERN.matcher(toExamine).matches();
}
这是Regex最有效的方式。
答案 4 :(得分:5)
尝试否定包含所有列入黑名单的字符类:
public boolean containsIllegals(String toExamine) {
return toExamine.matches("[^~#@*+%{}<>\\[\\]|\"\\_^]*");
}
如果字符串包含非法字符,则返回true
(在这种情况下,您的原始函数似乎返回false
。)
开头括号^
右侧的插入符号[
否定了字符类。请注意,在String.matches()
中,您不需要锚点^
和$
,因为它会自动匹配整个字符串。
答案 5 :(得分:2)
执行此操作的一种非常紧凑的方法是依赖String.replaceAll
方法:
public boolean containsIllegal(final String toExamine) {
return toExamine.length() != toExamine.replaceAll(
"[~#@*+%{}<>\\[\\]|\"\\_^]", "").length();
}