Подтвердить что ты не робот

Функция 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...
    }
}

Есть ли более элегантный/эффективный способ выполнения этого?

4b9b3361

Ответ 1

Здесь вы можете использовать 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). Мы можем разбить строку на данный шаблон и проверить длину массива. Если длина 1, то шаблон не был в строке.

public boolean containsIllegals(String toExamine) {
    String[] arr = toExamine.split("[~#@*+%{}<>\\[\\]|\"\\_^]", 2);
    return arr.length > 1;
}

Если arr.length > 1, это означает, что строка содержит один из символов в шаблоне, поэтому он был разделен. Я передал limit = 2 в качестве второго параметра в split, потому что мы в порядке только с одним split.

Ответ 2

Мне нужен метод сканирования каждого символа в строке

Если вы должны сделать это по-символу, 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];
}

Ответ 3

Если вы не можете использовать совпадение, вы можете сделать что-то вроде этого, что более чистое, чем куча разных операторов if или байтового массива.

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

Ответ 4

Используйте константу , чтобы избежать повторной компиляции регулярного выражения при каждой проверке.

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

И измените свой код на:

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

Это наиболее эффективный способ с Regex.

Ответ 5

Попробуйте отказаться от символьного класса, содержащего все черные списки:

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

Это вернет true, если строка содержит нелегалы ​​(ваша исходная функция, казалось, возвращала false в этом случае).

Каретка ^ справа от открывающей скобки [ отрицает класс символов. Обратите внимание, что в String.matches() вам не нужны привязки ^ и $, потому что они автоматически соответствуют всей строке.

Ответ 6

Довольно компактный способ сделать это - полагаться на метод String.replaceAll:

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