2012-02-09 16 views
7

que tienen una cadena comojava regex cuantificadores

String string = "number0 foobar number1 foofoo number2 bar bar bar bar number3 foobar"; 

Necesito una expresión regular que me diera el siguiente resultado:

number0 foobar 
number1 foofoo 
number2 bar bar bar bar 
number3 foobar 

He tratado

Pattern pattern = Pattern.compile("number\\d+(.*)(number\\d+)?"); 
Matcher matcher = pattern.matcher(string); 
while (matcher.find()) { 
    System.out.println(matcher.group()); 
} 

pero esto da

number0 foobar number1 foofoo number2 bar bar bar bar number3 foobar 
+0

¿Puede haber nuevas líneas en su cadena? –

+0

sí, tuve que agregar Pattern.DOTALL y funciona. Muchas gracias. – b3bop

Respuesta

10

¿Desea number (más un número entero) seguido de cualquier cosa hasta el siguiente number (o el final de la cadena), ¿verdad?

Luego hay que decir que el motor de expresiones regulares:

Pattern pattern = Pattern.compile("number\\d+(?:(?!number).)*"); 

En su expresión regular, el .* empareje tanto como pudo - todo hasta el final de la cadena. Además, hiciste la segunda parte (number\\d+)? como parte del juego.

Explicación de mi solución:

number # Match "number" 
\d+  # Match one of more digits 
(?:  # Match... 
(?!  # (as long as we're not right at the start of the text 
    number # "number" 
)  # ) 
.  # any character 
)*  # Repeat as needed. 
+1

esto es perfecto. gracias especialmente por la explicación. – b3bop

+1

@Tim Pietzcker, gracias por la respuesta! Siempre disfruto leyendo tus explicaciones detalladas. – aviad

0

porque .* es un patrón codicioso. utilizar .*? en lugar de .*

Pattern pattern = Pattern.compile("number\\d+(.*?)(number\\d+)"); 
Matcher matcher = pattern.matcher(string); 
while(matcher.find();){ 
    out(matcher.group()); 
} 
+0

Eso no va a funcionar, esto solo coincide con 'number0',' number1', 'number2' y' number3'. El segundo grupo es opcional (y no debería ser parte del partido.) –

+0

He editado la respuesta – shift66

+0

Todavía no coincide con el contenido correcto. Los resultados para la cadena de prueba son 'number0 foobar number1' y' number2 bar bar bar bar number3'. ¿No has probado tu código? (También falla si hay un número impar de 'number's en la cadena.) –

0

Si "foobar" es sólo un ejemplo y realmente quiere decir "palabra" utilice el siguiente patrón: (number\\d+)\s+(\\w+)

+0

Eso falla en' number2 bar bar bar bar'. –

+0

Right. I no prestó atención en múltiples 'barras'. Pero no es un problema arreglarlo: (número \\ d +) (?: \ s + (\\ w +)) + – AlexR

0

¿Por qué no acaba de coincidir para number\\d+, consultar la ubicación de partido, y hacer la cadena de dividir a sí mismo?

0
Pattern pattern = Pattern.compile("\\w+\\d(\\s\\w+)\1*"); 
Matcher matcher = pattern.matcher(string); 

while (matcher.find()) { 
    System.out.println(matcher.group()); 
} 
+0

Buen uso de [backreference] (https://docs.oracle.com/javase/tutorial/essential /regex/groups.html)!Sin embargo, esto no funcionará cuando intente hacer coincidir "barra barra foo number4 bar", que podría ser a lo que apunta el OP (en ese caso, se devuelve "barra núm4" en lugar de "barra bar foo number4"). –