Шаблон Java REGEX, если не соответствует

Я пытаюсь использовать Java Pattern и Matcher для проверки ввода. У меня он работает в действительно базовом формате, которым я пока доволен. Он применяет REGEX к аргументу, а затем перебирает совпадающие символы.

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexUtil {

   public static void main(String[] args) {

      String    argument;
      Pattern   pattern;
      Matcher   matcher;

      argument = "#a1^b2";
      pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s");
      matcher = pattern.matcher(argument);

      // find all matching characters
      while(matcher.find()) {
         System.out.println(matcher.group());
      }

   }

}

Это нормально для извлечения всех хороших символов, я получаю вывод

a
1
b
2

Теперь я хотел узнать, можно ли сделать то же самое для любых символов, которые не соответствуют REGEX, поэтому я получаю результат

#
^

Или еще лучше прокрутите его и получите флаги TRUE или FALSE для каждого индекса аргумента

false
true
true
false
true
true

Я знаю только, как выполнить цикл с помощью matcher.find (), любая помощь будет принята с благодарностью

[^a-zA-Z0-9] выдаст вам все символы, не соответствующие диапазону, поэтому: # ^
Jérôme 09.03.2018 14:32
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
2 252
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Вам нужно перебрать каждый char из String и проверить один за другим:

//for-each loop, shorter way
for (char c : argument.toCharArray()){
    System.out.println(pattern.matcher(c + "").matches());
}

или же

//classic for-i loop, with details
for (int i = 0; i < argument.length(); i++) {
    String charAtI = argument.charAt(i) + "";
    boolean doesMatch = pattern.matcher(charAtI).matches();
    System.out.println(doesMatch);
}

Кроме того, если вам это не нужно, вы можете объявить и указать значение одновременно:

String argument = "#a1^b2";
Pattern pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s");
Ответ принят как подходящий

Вы можете добавить альтернативу |(.) к своему шаблону (чтобы соответствовать любому символу, кроме символа разрыва строки) и проверять, соответствует ли Группа 1 при каждом совпадении. Если да, выведите ложный, иначе выведите правда:

String argument = "#a1^b2";
Pattern pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s|(.)"); // or "[a-zA-Z0-9\\s]|(.)"
Matcher matcher = pattern.matcher(argument);

while(matcher.find()) {                           // find all matching characters
    System.out.println(matcher.group(1) == null);

Смотрите Демонстрация Java, вывод:

false
true
true
false
true
true

Обратите внимание, что здесь вам не нужно использовать Pattern.DOTALL, потому что \s в вашем «белом списке» части шаблона соответствует разрывам строк.

Условие проверки для вывода логического значения можно упростить как базовый while (matcher.find()) { System.out.println(matcher.group(1) == null); }.

azro 09.03.2018 14:34

@azro Да, я просто подумал, что может потребоваться настраиваемая строка, если нужны только значения true или false, тогда конечно.

Wiktor Stribiżew 09.03.2018 14:35

Мне очень нравится этот ответ, но у меня есть вопрос о группе. Если я создам две группы "([a-zA-Z] | [0-9] | \\ s) | (.)" Для ясности, то почему matcher.group (2) не дает мне каждый символ в цикле?

TheLovelySausage 09.03.2018 14:59

@Trent Потому что Группа 1 будет их держать. Регулярное выражение в основном разбивает строку на два типа символов: те, которые вы хотите пометить как правда, и те, которые должны быть ложный.

Wiktor Stribiżew 09.03.2018 15:00

Хорошо, так что все, что соответствует группе 1, не может совпадать дважды и не совпадать с группой 2?

TheLovelySausage 09.03.2018 15:02

@ Трент Извини, я тебя не понимаю. Если вы просто хотите распечатать совпадение, распечатайте его с помощью matcher.group(0).

Wiktor Stribiżew 09.03.2018 15:18

Ничего страшного, я должен немного повозиться, но этот ответ идеально подходит для того, что мне нужно, большое спасибо

TheLovelySausage 09.03.2018 15:21

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

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexUtil {

   public static void main(String[] args) {

      String    argument;
      Pattern   pattern;
      Matcher   matcher;

      argument = "#a1^b2";
      pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s");
      matcher = pattern.matcher(argument);

      // find all matching characters
      while(matcher.find()) {
         System.out.println(matcher.group());
         argument = argument.replace(matcher.group(), "");
      }

      System.out.println("argument: " + argument);

   }

}

Отслеживайте позиции и для каждого совпадения выводите символы между последним совпадением и текущим совпадением.

int pos = 0;
while (matcher.find()) {
    for (int i = pos; i < matcher.start(); i++) {
        System.out.println(argument.charAt(i));
    }
    pos = matcher.end();
}
// Print any trailing characters after last match.
for (int i = pos; i < argument.length(); i++) {
    System.out.println(argument.charAt(i));
}

Одно из решений

    String  argument;
    Pattern pattern;
    Matcher matcher;

    argument = "#a1^b2";
    List<String> charList = Arrays.asList(argument.split(""));
    pattern = Pattern.compile("[a-zA-Z]|[0-9]|\\s");
    matcher = pattern.matcher(argument);
    ArrayList<String> unmatchedCharList = new ArrayList<>();
    // find all matching
    while(matcher.find()) {
        unmatchedCharList.add(matcher.group());
    }
    for(String charr : charList)
    {
        System.out.println(unmatchedCharList.contains(charr ));
    }

Выход

ложный правда правда ложный правда правда

Другие вопросы по теме