2011-02-10 18 views
14

Sto cercando di eseguire alcuni file di log super semplice analisi o, quindi sto usando String.split metodo come questo:Fuga virgola quando si utilizza String.split

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

e funziona alla grande per l'ingresso come:

a,b,c 

O

type=simple, output=Hello, repeat=true 

tanto per dire qualcosa.

Come posso evitare la virgola, quindi non corrisponde alle virgole intermedie?

Per esempio, se voglio includere una virgola in una delle parti:

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

Stavo pensando a qualcosa di simile:

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

Ma io non so come creare la divisione per evitare la corrispondenza con la virgola.

ho provato:

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

Ma, beh, non funziona.

+0

io upvote la tua domanda in 2 ore (! Sono fuori di voti per oggi) – aioobe

+0

Guava Problema 412: Aggiungere funzionalità di fuga verso Joiner e Splitter http://goo.gl/pfSCb – oluies

+0

@oluies: -O OscarRyz

risposta

21

È possibile risolverlo utilizzando negative look behind.

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

Fondamentalmente si dice, diviso su ogni ", " che non è preceduto da un backslash.

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

uscita:

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

(ideone.com link)


Se vi capita di essere bloccato con i valori non-escape separati da virgola, si potrebbe procedere come segue (simile) hack:

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

che dice diviso su ogni ", " che è seguita da alcuni word-personaggi e un =

(ideone.com link)

+1

Una risposta abbastanza interessante, ma non alla sua domanda 'Come posso sfuggire alla virgola, quindi non corrisponde alle virgole intermedie? ' – Zeemee

+2

Soluzione piacevole, ma IMHO per il problema sbagliato. Mentre una tale stringa può essere analizzata usando questo, fallirà un giorno con qualcuno che dice 'type = simple, output = Hello, world, repeat = fino a domani, o forse fino a 0 = 1'. Suggerirei un adeguato meccanismo di fuga invece di essere troppo intelligente. – maaartinus

+0

Buon punto. Per essere onesti, ho letto male la domanda. Aggiornato. – aioobe

0

Penso

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

dovrebbe funzionare. Sarà diviso in tutte le virgole che non sono preceduti da una barra rovesciata. BTW se si sta lavorando con Eclipse, posso raccomandare il plugin QuickRex per testare ed eseguire il debug di Regexes.

+0

Questo è quasi corretto, ma non perfetto in quanto non consente di fuggire backslash. Mangerà il personaggio prima del backslash. Farebbe un lookbehind – maaartinus

+0

Non ho problemi a scappare con qualcos'altro: P Tying ... – OscarRyz

+1

@maaartinus: Sì, hai ragione ... – Zeemee

4

ho paura, non c'è soluzione perfetta per String.split. Usare un accoppiatore per le tre parti funzionerebbe.Nel caso in cui il numero di parti non sia costante, raccomanderei un ciclo con matcher.find. Qualcosa di simile a questo forse

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)); 

Probabilmente desidera saltare gli spazi dopo la virgola così:

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

Non è davvero complicato, basta notare che è necessario quattro barre inverse, al fine di corrispondere a uno .

+0

+1 Ancora masticando che ... – OscarRyz

+0

È facile: il gruppo è una sequenza composta da 1. caratteri normali (ad esempio qualsiasi eccetto backslash e virgola) e 2. qualsiasi carattere di escape (cioè barra rovesciata seguita da qualsiasi cosa). Il resto è la virgola di separazione o l'ancora di fondo. – maaartinus

+0

Se si segue la rotta Pattern/Matcher, dovrebbe esserci un 'matcher 'più semplice.trovare una soluzione in grado di trovare una coppia chiave/valore alla volta, no? – aioobe

2

Sfuggire opere con l'opposto della risposta di aioobe (aggiornato: aioobe ora utilizza lo stesso costrutto, ma non sapevo che quando ho scritto questo), lookbehind 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("\\,", ",") + "'"); 
} 

uscita:

'type = semplice'

'uscita = Ciao, mondo' 'Ripetere le = true'

Riferimento:

Problemi correlati