Diferencia entre coincidencias () y encontrar () en Java Regex

250

Estoy tratando de entender la diferencia entre matches()y find().

Según el Javadoc, (por lo que entiendo), matches()buscará toda la cadena incluso si encuentra lo que está buscando, y find()se detendrá cuando encuentre lo que está buscando.

Si esa suposición es correcta, no puedo ver cada vez que quiera usar en matches()lugar de find(), a menos que desee contar la cantidad de coincidencias que encuentra.

En mi opinión, la clase String debería tener en find()lugar de matches()un método incorporado.

Entonces para resumir:

  1. ¿Es correcta mi suposición?
  2. ¿Cuándo es útil usar en matches()lugar de find()?
Shervin Asgari
fuente
2
Tenga en cuenta que llamar find()varias veces puede devolver resultados diferentes para el mismo Matcher. Vea mi respuesta a continuación.
L. Holanda

Respuestas:

300

matchesintenta hacer coincidir la expresión con la cadena completa e implícitamente agrega un ^al comienzo y $al final de su patrón, lo que significa que no buscará una subcadena. De ahí la salida de este código:

public static void main(String[] args) throws ParseException {
    Pattern p = Pattern.compile("\\d\\d\\d");
    Matcher m = p.matcher("a123b");
    System.out.println(m.find());
    System.out.println(m.matches());

    p = Pattern.compile("^\\d\\d\\d$");
    m = p.matcher("123");
    System.out.println(m.find());
    System.out.println(m.matches());
}

/* output:
true
false
true
true
*/

123es una subcadena de a123bmodo que el find()método genera verdadero. matches()solo "ve", a123bque no es lo mismo 123y, por lo tanto, genera falso

Sanjay T. Sharma
fuente
25
Esta respuesta es engañosa. matchers()no es simplemente un find()con envolvente implícito ^ y $. Tenga en cuenta que llamar .find()más de una vez puede tener resultados diferentes si no está precedido por reset(), mientras matches()que siempre devolverá el mismo resultado. Vea mi respuesta a continuación.
L. Holanda
80

matchesdevuelve verdadero si la cadena completa coincide con el patrón dado. findintenta encontrar una subcadena que coincida con el patrón.

Khachik
fuente
35
Se podría decir que matches(p)es lo mismo que find("^" + p + "$")si fuera más claro.
jensgram
44
Solo un ejemplo para aclarar la respuesta: "[az] +" con la cadena "123abc123" fallará al usar coincidencias () pero tendrá éxito usando find ().
bezmax
3
@Max Exactamente, "123abc123".matches("[a-z]+")fallará igual que lo "123abc123".find("^[a-z]+$")haría. Mi punto fue que eso se matches()aplica a un partido completo, al igual que find()con los anclajes de inicio y final.
jensgram
55
Pattern.compile("some pattern").matcher(str).matches()es igual aPattern.compile("^some pattern$").matcher(str).find()
AlexR
3
@AlexR / @jensgram: no...("some pattern").matcher(str).matches() es exactamente igual a eso solo es cierto en la primera llamada. Vea mi respuesta a continuación. ...("^some pattern$").matcher(str).find()
L. Holanda
62

matches()solo devolverá verdadero si la cadena completa coincide. find()intentará encontrar la próxima aparición dentro de la subcadena que coincida con la expresión regular. Tenga en cuenta el énfasis en "el próximo". Eso significa que el resultado de llamar find()varias veces podría no ser el mismo. Además, mediante el uso find()puede llamar start()para devolver la posición de la subcadena.

final Matcher subMatcher = Pattern.compile("\\d+").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + subMatcher.matches());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find() + " - position " + subMatcher.start());
System.out.println("Found: " + subMatcher.find());
System.out.println("Found: " + subMatcher.find());
System.out.println("Matched: " + subMatcher.matches());

System.out.println("-----------");
final Matcher fullMatcher = Pattern.compile("^\\w+$").matcher("skrf35kesruytfkwu4ty7sdfs");
System.out.println("Found: " + fullMatcher.find() + " - position " + fullMatcher.start());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Found: " + fullMatcher.find());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());
System.out.println("Matched: " + fullMatcher.matches());

Saldrá:

Encontrado: falso
Encontrado: verdadero - posición 4
Encontrado: verdadero - posición 17
Encontrado: verdadero - posición 20
Encontrado: falso
Encontrado: falso
Emparejado: falso
-----------
Encontrado: verdadero - posición 0
Encontrado: falso
Encontrado: falso
Emparejado: verdadero
Emparejado: verdadero
Emparejado: verdadero
Emparejado: verdadero

Por lo tanto, tenga cuidado al llamar find()varias veces si el Matcherobjeto no se restableció, incluso cuando la expresión regular está rodeada ^y $coincide con la cadena completa.

L. Holanda
fuente
2
compañero muy útil
DockYard
6

find()considerará la subcadena contra la expresión regular donde como matches()considerará la expresión completa.

find() will devuelve verdadero solo si la subcadena de la expresión coincide con el patrón.

public static void main(String[] args) {
        Pattern p = Pattern.compile("\\d");
        String candidate = "Java123";
        Matcher m = p.matcher(candidate);

        if (m != null){
            System.out.println(m.find());//true
            System.out.println(m.matches());//false
        }
    }
Sumanth Varada
fuente
3

matches();no amortigua, pero find()amortigua. find()busca primero el final de la cadena, indexa el resultado y devuelve el valor booleano y el índice correspondiente.

Es por eso que cuando tienes un código como

1:Pattern.compile("[a-z]");

2:Pattern.matcher("0a1b1c3d4");

3:int count = 0;

4:while(matcher.find()){

5:count++: }

A las 4: el motor de expresiones regulares que utiliza la estructura del patrón leerá todo el código (indexar a indexar según lo especificado por regex[single character]para encontrar al menos una coincidencia. Si se encuentra dicha coincidencia, se indexará y el bucle se ejecutará en función de el resultado indexado de lo contrario si no hiciera un cálculo anticipado como cuál matches(); no. La instrucción while nunca se ejecutaría ya que el primer carácter de la cadena coincidente no es un alfabeto.


fuente