Grupos de captura de Java Regex

Estoy tratando de entender este bloque de código. En el primero, ¿qué es lo que estamos buscando en la expresión?

Según entiendo, se trata de cualquier carácter (0 o más veces *) seguido de cualquier número entre 0 y 9 (una o más veces +) seguido de cualquier carácter (0 o más veces *).

Cuando esto se ejecuta, el resultado es:

Found value: This order was placed for QT3000! OK? Found value: This order was placed for QT300 Found value: 0 

¿Alguien podría pasar por esto conmigo?

¿Cuál es la ventaja de usar grupos de captura?

 import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTut3 { public static void main(String args[]) { String line = "This order was placed for QT3000! OK?"; String pattern = "(.*)(\\d+)(.*)"; // Create a Pattern object Pattern r = Pattern.compile(pattern); // Now create matcher object. Matcher m = r.matcher(line); if (m.find()) { System.out.println("Found value: " + m.group(0)); System.out.println("Found value: " + m.group(1)); System.out.println("Found value: " + m.group(2)); } else { System.out.println("NO MATCH"); } } } 

El problema que estás teniendo es con el tipo de cuantificador. Está utilizando un cuantificador codicioso en su primer grupo (índice 1 – el índice 0 representa todo el Pattern ), lo que significa que coincidirá tanto como le sea posible (y dado que es cualquier personaje, coincidirá con tantos caracteres como haya) son para cumplir la condición para los siguientes grupos).

En resumen, su primer grupo .* Coincide con cualquier cosa siempre que el siguiente grupo \\d+ pueda coincidir con algo (en este caso, el último dígito).

Según el tercer grupo, coincidirá con cualquier cosa después del último dígito.

Si lo cambia a un cuantificador reacio en su primer grupo, obtendrá el resultado que supongo que está esperando, es decir, la parte de 3000 .

Tenga en cuenta el signo de interrogación en el primer grupo.

 String line = "This order was placed for QT3000! OK?"; Pattern pattern = Pattern.compile("(.*?)(\\d+)(.*)"); Matcher matcher = pattern.matcher(line); while (matcher.find()) { System.out.println("group 1: " + matcher.group(1)); System.out.println("group 2: " + matcher.group(2)); System.out.println("group 3: " + matcher.group(3)); } 

Salida:

 group 1: This order was placed for QT group 2: 3000 group 3: ! OK? 

Más información sobre el Pattern Java aquí .

Finalmente, los grupos de captura están delimitados por corchetes, y proporcionan una forma muy útil de utilizar referencias retrospectivas (entre otras cosas), una vez que su Pattern coincide con la entrada.

En Java 6 los grupos solo pueden ser referenciados por su orden (cuidado con los grupos nesteds y la sutileza de los pedidos).

En Java 7 es mucho más fácil, ya que puedes usar grupos con nombre.

Esto está totalmente bien.

  1. El primer grupo ( m.group(0) ) siempre captura toda el área que está cubierta por su expresión regular . En este caso, es toda la cadena.
  2. Las expresiones regulares son codiciosas por defecto, lo que significa que el primer grupo captura tanto como sea posible sin violar la expresión regular. El (.*)(\\d+) (la primera parte de su expresión regular) cubre el ...QT300 int en el primer grupo y el 0 en el segundo.
  3. Puede solucionarlo rápidamente haciendo que el primer grupo no sea codicioso: cambie (.*) (.*?) .

Para obtener más información sobre avaro vs perezoso, visite este sitio.

Su comprensión es correcta. Sin embargo, si revisamos:

  • (.*) tragará toda la cadena;
  • necesitará devolver caracteres para que (\\d+) esté satistificado (por lo que se captura 0 y no 3000 );
  • el último (.*) capturará el rest.

Sin embargo, no estoy seguro de cuál era la intención original del autor.

Del doc:

 Capturing groups are indexed from left * to right, starting at one. Group zero denotes the entire pattern, so * the expression m.group(0) is equivalent to m.group(). 

Así que captura el grupo 0 envía toda la línea.