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

Совпадение совпадений java regex

Скажем, у меня есть файл, и файл содержит следующее:

HelloxxxHelloxxxHello

Я скомпилирую шаблон для поиска 'Hello'

Pattern pattern = Pattern.compile("Hello");

Затем я использую входной поток для чтения в файле и преобразовываю его в String, чтобы он мог быть regexed.

Как только совпад находит совпадение в файле, он указывает это, но он не говорит мне, сколько совпадений найдено; просто, что он нашел совпадение внутри строки.

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

Самый простой способ подсчета количества совпадений, которые произошли в String. Я пробовал различные для циклов и использовал matcher.groupCount(), но я не получаю никуда быстро.

4b9b3361

Ответ 1

matcher.find() не находит все совпадения, только следующее совпадение.

Вам нужно будет сделать следующее:

int count = 0;
while (matcher.find())
    count++;

Кстати, matcher.groupCount() - это нечто совершенно другое.

Полный пример:

import java.util.regex.*;

class Test {
    public static void main(String[] args) {
        String hello = "HelloxxxHelloxxxHello";
        Pattern pattern = Pattern.compile("Hello");
        Matcher matcher = pattern.matcher(hello);

        int count = 0;
        while (matcher.find())
            count++;

        System.out.println(count);    // prints 3
    }
}

Обработка совпадений матчей

При подсчете совпадений aa в aaaa приведенный выше фрагмент даст вам 2.

aaaa
aa
  aa

Чтобы получить 3 совпадения, то есть это поведение:

aaaa
aa
 aa
  aa

Вы должны искать совпадение по индексу <start of last match> + 1 следующим образом:

String hello = "aaaa";
Pattern pattern = Pattern.compile("aa");
Matcher matcher = pattern.matcher(hello);

int count = 0;
int i = 0;
while (matcher.find(i)) {
    count++;
    i = matcher.start() + 1;
}

System.out.println(count);    // prints 3

Ответ 2

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

public static void main(String[] args) {
    String input = "aaaaaaaa";
    String regex = "aa";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(input);
    int from = 0;
    int count = 0;
    while(matcher.find(from)) {
        count++;
        from = matcher.start() + 1;
    }
    System.out.println(count);
}

Ответ 3

Если вы хотите использовать потоки Java 8 и имеете аллергию на циклы while, вы можете попробовать это:

public static int countPattern(String references, Pattern referencePattern) {
    Matcher matcher = referencePattern.matcher(references);
    return Stream.iterate(0, i -> i + 1)
            .filter(i -> !matcher.find())
            .findFirst()
            .get();
}

Отказ от ответственности: это работает только для непересекающихся матчей.

Пример:

public static void main(String[] args) throws ParseException {
    Pattern referencePattern = Pattern.compile("PASSENGER:\\d+");
    System.out.println(countPattern("[ \"PASSENGER:1\", \"PASSENGER:2\", \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
    System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
    System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\", \"PASSENGER:1\" ]", referencePattern));
    System.out.println(countPattern("[  ]", referencePattern));
}

Это распечатывает:

2
0
1
0

Это решение для несвязанных совпадений с потоками:

public static int countPattern(String references, Pattern referencePattern) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            new Iterator<Integer>() {
                Matcher matcher = referencePattern.matcher(references);
                int from = 0;

                @Override
                public boolean hasNext() {
                    return matcher.find(from);
                }

                @Override
                public Integer next() {
                    from = matcher.start() + 1;
                    return 1;
                }
            },
            Spliterator.IMMUTABLE), false).reduce(0, (a, c) -> a + c);
}

Ответ 4

Это может помочь:

public static void main(String[] args) {
    String hello = "HelloxxxHelloxxxHello";
    String []matches = hello.split("Hello");
    System.out.println(matches.length);    // prints 3
}

Ответ 5

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

        Pattern p = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL);// "regex" here indicates your predefined regex.
        Matcher m = p.matcher(pattern); // "pattern" indicates your string to match the pattern against with
        boolean b = m.matches();
        if(b)
        count++;
        while (m.find())
        count++;

Это обобщенный, а не специфический код, адаптируйте его под свои нужды

Пожалуйста, не стесняйтесь исправлять меня, если есть какая-либо ошибка.