Grupos de Captura Regex Java

Eu estou tentando entender esse bloco de código. Na primeira, o que estamos procurando na expressão?

Meu entendimento é que é qualquer caractere (0 ou mais vezes *) seguido por qualquer número entre 0 e 9 (uma ou mais vezes +) seguido por qualquer caractere (0 ou mais vezes *).

Quando isso é executado, o resultado é:

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

Alguém poderia por favor passar por isso comigo?

Qual é a vantagem 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"); } } } 

O problema que você está tendo é com o tipo de quantificador. Você está usando um quantificador guloso em seu primeiro grupo (índice 1 – o índice 0 representa o Pattern inteiro), o que significa que ele corresponderá tanto quanto puder (e como é qualquer caractere, ele corresponderá a tantos caracteres quanto estão em ordem para cumprir a condição para os próximos grupos).

Em suma, o seu primeiro grupo .* Corresponde a qualquer coisa, desde que o próximo grupo \\d+ possa corresponder a algo (neste caso, o último dígito).

De acordo com o 3º grupo, ele corresponderá a qualquer coisa após o último dígito.

Se você alterá-lo para um quantificador relutante em seu primeiro grupo, você obterá o resultado que eu suponho que você esteja esperando, isto é, a parte 3000 .

Observe o ponto de interrogação no 1º 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)); } 

Saída:

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

Mais informações sobre o Java Pattern aqui .

Finalmente, os grupos de captura são delimitados por parênteses e fornecem uma maneira muito útil de usar referências de retorno (entre outras coisas), uma vez que seu Pattern é combinado com a input.

No Java 6, os grupos só podem ser referenciados por sua ordem (cuidado com os grupos nesteds e com a sutileza de ordenação).

No Java 7 é muito mais fácil, como você pode usar grupos nomeados.

Isso é totalmente OK.

  1. O primeiro grupo ( m.group(0) ) sempre captura toda a área coberta pela sua expressão regular . Neste caso, é toda a string.
  2. Expressões regulares são gananciosas por padrão, o que significa que o primeiro grupo captura o máximo possível sem violar o regex. O (.*)(\\d+) (a primeira parte do seu regex) cobre o ...QT300 int o primeiro grupo e o 0 no segundo.
  3. Você pode corrigir isso rapidamente tornando o primeiro grupo não-ganancioso: altere (.*) Para (.*?) .

Para mais informações sobre gananciosos vs. preguiçosos, verifique este site.

Sua compreensão está correta. No entanto, se passarmos por:

  • (.*) engolirá a string inteira;
  • ele precisará retornar caracteres para que (\\d+) seja satistifed (é por isso que 0 é capturado e não 3000 );
  • o último (.*) irá capturar o resto.

Não tenho certeza qual foi a intenção original do autor.

Do 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(). 

Então, o grupo de captura 0 envia a linha inteira.