¿Cómo puedo contar el número de coincidencias para una expresión regular?


97

Digamos que tengo una cadena que contiene esto:

HelloxxxHelloxxxHello

Recopilo un patrón para buscar 'Hola'

Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher("HelloxxxHelloxxxHello");

Debería encontrar tres coincidencias. ¿Cómo puedo contar cuántas coincidencias hubo?

Probé varios bucles y usé el matcher.groupCount()pero no funcionó.


¿Existe alguna posibilidad de que su cadena de búsqueda tenga ocurrencias superpuestas en la cadena de entrada?
aioobe

Respuestas:


177

matcher.find()no encuentra todas las coincidencias, solo la siguiente .

Solución para Java 9+

long matches = matcher.results().count();

Solución para Java 8 y versiones anteriores

Tendrá que hacer lo siguiente. ( A partir de Java 9, hay una mejor solución )

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

Por cierto, matcher.groupCount()es algo completamente diferente.

Ejemplo completo :

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
    }
}

Manejo de coincidencias superpuestas

Al contar las coincidencias de aaen aaaael fragmento anterior, obtendrá 2 .

aaaa
aa
  aa

Para obtener 3 coincidencias, es decir, este comportamiento:

aaaa
aa
 aa
  aa

Debe buscar una coincidencia en el índice de la <start of last match> + 1siguiente manera:

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

Contando el número de coincidencias que ocurren dentro de la cadena. El método java.util.regex.Matcher.region (int start, int end) establece los límites de la región de este comparador. La región es la parte de la secuencia de entrada que se buscará para encontrar una coincidencia. La invocación de este método restablece el comparador y luego establece la región para que comience en el índice especificado por el parámetro de inicio y finalice en el índice especificado por el parámetro de fin. Prueba esto. while(matcher.find()){ matcher.region(matcher.end()-1, str.length()); count++; }
Mukesh Kumar Gupta

17

Esto debería funcionar para coincidencias que podrían superponerse:

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

Si desea utilizar secuencias de Java 8 y es alérgico a los whilebucles, puede probar esto:

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();
}

Descargo de responsabilidad: esto solo funciona para coincidencias disjuntas.

Ejemplo:

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));
}

Esto imprime:

2
0
1
0

Esta es una solución para coincidencias disjuntas con transmisiones:

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);
}

1

Use el siguiente código para encontrar el número de coincidencias que la expresión regular encuentra en su entrada

        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++;

Sin embargo, este es un código generalizado, no específico, adáptelo a sus necesidades

No dude en corregirme si hay algún error.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.