如果字符串包含非法字符,则返回Java函数

我有以下字符,我希望被视为“非法”:

~#@*+%{}<>[]|\_^

我想编写一个检查字符串的方法,并确定( true / false )该字符串是否包含这些非法字符:

 public boolean containsIllegals(String toExamine) { return toExamine.matches("^.*[~#@*+%{}[]|\"\\_^].*$"); } 

但是,简单matches(...)检查对此不可行。 我需要该方法来扫描字符串中的每个字符,并确保它不是这些字符之一。 当然,我可以做一些可怕的事情:

 public boolean containsIllegals(String toExamine) { for(int i = 0; i < toExamine.length(); i++) { char c = toExamine.charAt(i); if(c == '~') return true; else if(c == '#') return true; // etc... } } 

是否有更优雅/有效的方法来实现这一目标?

您可以在此处使用PatternMatcher类。 您可以将所有已过滤的字符放在字符类中,并使用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第二个参数,因为我们只需单个拆分即可。

我需要该方法来扫描字符串中的每个字符

如果你必须按字符逐个进行,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]; } 

如果您不能使用匹配器,那么您可以执行类似这样的操作,它比一堆不同的if语句或字节数组更清晰。

  for(int i = 0; i < toExamine.length(); i++) { char c = toExamine.charAt(i); if("~#@*+%{}<>[]|\"_^".contains(c)){ return true; } } 

使用常量来避免在每次validation中重新编译正则表达式。

 private static final Pattern INVALID_CHARS_PATTERN = Pattern.compile("^.*[~#@*+%{}<>\\[\\]|\"\\_].*$"); 

并将您的代码更改为:

 public boolean containsIllegals(String toExamine) { return INVALID_CHARS_PATTERN.matcher(toExamine).matches(); } 

这是Regex最有效的方法。

尝试否定包含所有列入黑名单的字符的字符类:

 public boolean containsIllegals(String toExamine) { return toExamine.matches("[^~#@*+%{}<>\\[\\]|\"\\_^]*"); } 

如果字符串包含非法字符,则返回true (在这种情况下,您的原始函数似乎返回false )。

插入符号^位于左括号的右侧[否定字符类别。 请注意,在String.matches()您不需要锚点^$因为它会自动匹配整个字符串。

一个非常紧凑的方法是依赖String.replaceAll方法:

 public boolean containsIllegal(final String toExamine) { return toExamine.length() != toExamine.replaceAll( "[~#@*+%{}<>\\[\\]|\"\\_^]", "").length(); }