2012-06-07 13 views
5

Tengo una cadena que coincide con esta expresión regular: ^.+:[0-9]+(\.[0-9]+)*/[0-9]+$ que se puede visualizar fácilmente como (Text):(Double)/(Int). Necesito dividir esta cadena en las tres partes. Normalmente esto sería fácil, excepto que el (Text) puede contener dos puntos, por lo que no puedo dividir dos puntos, sino el último dos puntos.Opcionalmente utilizando String.split(), divida una cadena en la última aparición de un delimitador

El .* es codicioso por lo que ya hace un trabajo bastante ordenado de hacer esto, pero esto no funcionará como una expresión regular en String.split() porque va a comer mi (Text) como parte del delimitador. Idealmente, me gustaría tener algo que devuelva un String [] con tres cadenas. Estoy 100% bien al no usar String.split() para esto.

Respuesta

3

¿Por qué no utiliza una expresión regular directa?

Pattern p = Pattern.compile("^(.*):([\\d\\.]+)/(\\d+)$"); 
Matcher m = p.matcher(someString); 
if (m.find()) { 
    m.group(1); // returns the text before the colon 
    m.group(2); // returns the double between the colon and the slash 
    m.group(3); // returns the integer after the slash 
} 

O similar. El patrón ^(.*):([\d\.]+)/(\d+)$ asume que usted realmente tiene valores en las tres posiciones, y solo permitirá un período/parada completa en la posición doble, por lo que es posible que desee ajustarlo según sus especificaciones.

+0

OK, ahora diga que en lugar de usar '[\ d \.] +' para que coincida con el doble, ¿y si quisiera ser estricto y exigir '\ d + (\. \ d +) *'. ¿Podría usar con seguridad solo los grupos 0,1,3? Es decir, 'sometext: other: 2/4' y 'sometext: other: grupo de alféizar 2.0/4' de la misma manera? – Huckle

+1

Serían los grupos 1, 2 y 4, pero no es necesario que se moleste con eso. Simplemente haga que el nuevo grupo sea uno que no lo capture : '\ d + (?: \. \ d +)?' –

+0

group (0) devuelve la cadena coincidente completa. Este es uno de los pocos casos en que re el índice no comienza en cero. @AlanMoore tiene una buena sugerencia para una estricta doble expresión regular. –

5

No me gusta la expresión regular (es una broma, pero no soy muy buena en eso).

String s = "asdf:1.0/1" 
String text = s.substring(0,s.lastIndexOf(":")); 
String doub = s.substring(s.lastIndexOf(":")+1,text.indexOf("/")); 
String inte = s.substring(text.indexOf("/")+1,s.length()); 
+0

su subcadena es incorrecta. Comienza en el índice 0 no en 1 – Subs

+0

@Subs: Quiero omitir el '(' . – tskuzzy

+0

) inicial Él dijo '()' para fines de visualización. No pienses que esos corchetes vienen en – Subs

1

String.split() se usa generalmente en escenarios más simples donde el delimitador y el formateo son más consistentes y cuando no se sabe cuántos elementos se van a dividir.

Su caso de uso requiere una expresión normal antigua normal. Ya conoce el formato de la cadena, y sabe que quiere recopilar tres valores. Pruebe algo como lo siguiente.

Pattern p = Pattern.compile("(.+):([0-9\\.]+)/([0-9]+)$"); 
Matcher m = p.matcher(myString); 
if (m.find()) { 
    String myText = m.group(1); 
    String myFloat = m.group(2); 
    String myInteger = m.group(3); 
} 
Cuestiones relacionadas