2011-02-10 29 views
14

Estoy intentando realizar algunos análisis de archivos de registro o muy simples, por lo que estoy usando String.split método como este:escape coma cuando se utiliza String.split

String [] parts = input.split(","); 

y funciona muy bien para la entrada como:

a,b,c 

O

type=simple, output=Hello, repeat=true 

sólo para decir algo.

¿Cómo puedo escapar de la coma, por lo que no coincide con las comas intermedias?

Por ejemplo, si quiero incluir una coma en una de las partes:

type=simple, output=Hello, world, repeate=true 

que estaba pensando en algo como:

type=simple, output=Hello\, world, repeate=true 

Pero no sé cómo crear la división para evitar que coincida con la coma.

que he probado:

String [] parts = input.split("[^\,],"); 

Pero, bueno, no está funcionando.

+0

Voy a upvote su pregunta en 2 horas (! Estoy fuera de votos por hoy) – aioobe

+0

guayaba Edición 412: Agregar funcionalidad de escape a Joiner y Splitter http://goo.gl/pfSCb – oluies

+0

@oluies: -O OscarRyz

Respuesta

21

Puede resolverlo usando negative look behind.

String[] parts = str.split("(?<!\\\\), "); 

Básicamente se dice, dividida en cada ", " que no está precedido por una barra invertida.

String str = "type=simple, output=Hello\\, world, repeate=true"; 
String[] parts = str.split("(?<!\\\\), "); 
for (String s : parts) 
    System.out.println(s); 

Salida:

type=simple 
output=Hello\, world 
repeate=true 

(ideone.com link)


Si le sucede a ser pegado con los valores no escaparon separados por comas, se puede hacer lo siguiente (similar) hackear:

String[] parts = str.split(", (?=\\w+=)"); 

¿Qué dice dividida en cada ", " que es seguido por algunas palabras-personajes y un =

(ideone.com link)

+1

Bastante una respuesta interesante, pero no a su pregunta '¿Cómo puedo escapar de la coma, por lo que no coincide con las comas intermedias? – Zeemee

+2

Buena solución, pero en mi humilde opinión para el problema equivocado. Si bien una cadena así puede ser analizada usando esto, fallará algún día cuando alguien diga 'type = simple, output = Hello, world, repeat = hasta mañana, o tal vez hasta 0 = 1'. Sugeriría un mecanismo de escape adecuado en lugar de ser demasiado inteligente. – maaartinus

+0

Buen punto. Para ser honesto, leí mal la pregunta. Actualizado. – aioobe

0

creo

input.split("[^\\\\],"); 

debería funcionar. Se dividirá en todas las comas que no estén precedidas por una barra invertida. BTW si está trabajando con Eclipse, puedo recomendar el complemento QuickRex para probar y depurar Regexes.

+0

Esto es casi correcto, pero no es perfecto, ya que no permite escapar de las barras diagonales inversas. Se comerá el personaje antes de la barra invertida. Un vistazo detrás haría. – maaartinus

+0

No tengo ningún problema escapando con otra cosa: P Probar ... – OscarRyz

+1

@maaartinus: Sí, tienes razón ... – Zeemee

4

me temo, no hay solución perfecta para String.split. Usar un matcher para las tres partes funcionaría.En caso de que el número de partes no sea constante, recomendaría un ciclo con matcher.find. Algo como esto quizá

final String s = "type=simple, output=Hello, world, repeat=true"; 
final Pattern p = Pattern.compile("((?:[^\\\\,]|\\\\.)*)(?:,|$)"); 
final Matcher m = p.matcher(s); 
while (m.find()) System.out.println(m.group(1)); 

Es probable que desea omitir los espacios después de la coma, así:

final Pattern p = Pattern.compile("((?:[^\\\\,]|\\\\.)*)(?:,\\s*|$)"); 

En realidad no es complicado, sólo en cuenta que necesita cuatro barras invertidas con el fin de coincidir con uno .

+0

+1 Aún masticando ... – OscarRyz

+0

Es fácil: el grupo es una secuencia que consta de 1. caracteres normales (es decir, cualquiera excepto barra invertida y coma) y 2. cualquier carácter escapado (es decir, barra invertida seguida de cualquier cosa). El resto es la coma separadora o el anclaje final. – maaartinus

+0

Si va por la ruta Patrón/Matcher, debería haber un 'emparejador 'más simple.encontrar una solución que pueda encontrar un par de clave/valor a la vez, ¿no? – aioobe

2

Escapar obras con lo contrario de la respuesta de aioobe (actualizado: aioobe ahora utiliza la misma construcción pero yo no sabía que cuando escribí esto), de búsqueda hacia atrás negativo

final String s = "type=simple, output=Hello\\, world, repeate=true"; 
final String[] tokens = s.split("(?<!\\\\),\\s*"); 
for(final String item : tokens){ 
    System.out.println("'" + item.replace("\\,", ",") + "'"); 
} 

Salida:

'type = simple'

'de salida = Hola, mundo' 'repeate = true'

Referencia:

Cuestiones relacionadas