Como iterar sobre matches ( múltiplos Matcher ) : expressão regular / regex Java

4 respostas
R

Pessoal
Estou tentando iterar sobre resultados de uma expressão regular no Java, mas a API não me proporciona algo para isso !

Ex: A API me oferece uma forma de iterar sobre os grupos retornados, já que há o método Matcher.groupCount(). MAS a API não me oferece nada do tipo Matcher.matchesCount(). E o que ela me oferece ( Pattern.split e Matcher.find ) não sei se estou usando errado ou se não servem para o que eu quero !

Demonstração do “resultado” pretendido:
Match1:
… grupo1 - 01
… grupo2 - xxxx-xxxx-xxxx-xxxx
Match2:
… grupo1 - 02
… grupo2 - yyyy-yyyy-yyyy-yyyy

Abaixo, as partes do código que importam:
1 (tentando usar Pattern.split) :

String response = "  General_Result=OK      Product=<produto01>   LicenseCode=xxxx-xxxx-xxxx-xxxx    Product=<produto02>     LicenseCode=yyyy-yyyy-yyyy-yyyy ";
            regularExpression = ".*?[Ppr]oduct\\s*=\\s*[\\<\\-\\w]{4,9}([\\d]{1,3}).*?[lL]icense[cC]ode\\s*=\\s*([\\d\\-\\w]{4,20}).*?";
            regexPattern = Pattern.compile(regularExpression, Pattern.DOTALL);
            String[] regexMatches = regexPattern.split(response);
            for (int i = 0; i < regexMatches.length; i++) {
                regexMatcher = regexPattern.matcher(regexMatches[i]);
                if (regexMatcher.matches()) {
                    int productId = Integer.parseInt(regexMatcher.group(1));
                    String licenseCode = regexMatcher.group(2);
                    ServicesType[] servicesCodes = getServicesCodesByProductId(productId);
                    licensesMap.put(licenseCode, servicesCodes);
                }
            }

[color=red]Problema: o String array retornado do split vem com 3 resultados vazio ("").[/color]

2 (tentando usar Matcher.find):

String response = "  General_Result=OK      Product=<produto01>   LicenseCode=xxxx-xxxx-xxxx-xxxx    Product=<produto02>     LicenseCode=yyyy-yyyy-yyyy-yyyy ";
regularExpression = ".*?[Ppr]oduct\\s*=\\s*[\\<\\-\\w]{4,9}([\\d]{1,3}).*?[lL]icense[cC]ode\\s*=\\s*([\\d\\-\\w]{4,20}).*?";
regexPattern = Pattern.compile(regularExpression, Pattern.DOTALL);
regexMatcher = regexPattern.matcher(response);
if (regexMatcher.matches()) {
    while (regexMatcher.find()) {
      int productId = Integer.parseInt(regexMatcher.group(1));
      String licenseCode = regexMatcher.group(2);
    }
}

[color=red]Problema: ao atingir o “while (regexMatcher.find())”, sai da condição direto.[/color]

[color=darkblue]3 - acabei de tentar tambem vendo se o java trata os matches como grupos. Por ex: Eu estava esperando 2 matches cada um com 2 grupos. Se o que estava pensando acontecesse eu deveria ter 4 grupos em Matcher.groupCount() . Mas só tenho 2 mesmo ( o que significa que estou no primeiro match ). Este primeiro match por sinal, funciona perfeitamente; MAS COMO EU FAÇO PARA ITERAR PARA O PRÓXIMO MATCH ???[/color]

.

4 Respostas

T

Vou dar um exemplo com uma expressão mais simples, só para ficar fácil de ver. Sou ruim para entender o código das outras pessoas…

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExemploMatcher {
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		String str = "<font color='red' face='Helvetica'>A</font><font color='blue' face='Times'>B</font>";
		Pattern pat = Pattern.compile ("color='([A-Za-z]+)' face='([A-Za-z]+)'");
		Matcher mat = pat.matcher(str);
		int i = 0;
		while (mat.find()) {
			System.out.printf ("Achou [%s]%n", mat.group());
			i = i + 1;
			System.out.printf ("%d. ", i);
			for (int j = 1; j &lt;= mat.groupCount(); ++j) {
				System.out.printf( " Grupo %d = [%s]; ", j, mat.group(j));
			}
			System.out.println();
		}
	}
}

A saída esperada é:

Achou [color='red' face='Helvetica']
1.  Grupo 1 = [red];  Grupo 2 = [Helvetica]; 
Achou [color='blue' face='Times']
2.  Grupo 1 = [blue];  Grupo 2 = [Times];
R

Valew ! Vou tentar !

R

Legal !
Também descobri o problema, mas não entendi o motivo !

Tente colocar um “if (matcher.matches()) {” antes de iterar sobre o método matcher.find() pra você ver !
Ele retorna FALSE !!! :shock:

PORQUE ???

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ExemploMatcher {
    /**
     * @param args
     */
    public static void main(String[] args) {
        String str = "<font color='red' face='Helvetica'>A</font><font color='blue' face='Times'>B</font>";
        Pattern pat = Pattern.compile("color='([A-Za-z]+)' face='([A-Za-z]+)'");
        Matcher matcher = pat.matcher(str);
        if (matcher.matches()) {
            int i = 0;
            while (matcher.find()) {
                System.out.printf("Achou [%s]%n", matcher.group());
                i = i + 1;
                System.out.printf("%d. ", i);
                for (int j = 1; j <= matcher.groupCount(); ++j) {
                    System.out
                            .printf(" Grupo %d = [%s]; ", j, matcher.group(j));
                }
                System.out.println();
            }
        }
    }
}
T

O método “matches” força a string inteira a bater com a expressão regular (é como se você tivesse posto um “^”…"$" na expressão regular). Isso quer dizer que ele sempre iria retornar FALSE, já que você quer achar várias ocorrências da expressão regular.

Criado 4 de junho de 2008
Ultima resposta 5 de jun. de 2008
Respostas 4
Participantes 2