2011-02-10 11 views
14

Próbuję wykonać kilka prostych plików dziennika Super parsowanie O, więc używam String.split metoda tak:Ucieczka przecinek przy użyciu String.split

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

I działa świetnie na wejściu jak:

a,b,c 

Albo

type=simple, output=Hello, repeat=true 

tylko coś powiedzieć.

Jak mogę uniknąć przecinka, aby nie pasował do przecinków pośrednich?

Na przykład, jeśli chcę to przecinek w jednej z części:

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

Myślałam coś jak:

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

Ale nie wiem, jak tworzyć podział, aby uniknąć dopasowania przecinka.

Próbowałem:

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

Ale cóż, nie działa.

+0

będę upvote zapytanie w ciągu 2 godzin (! Jestem z głosami do dzisiaj) – aioobe

+0

Guava Issue 412: Dodaj do ucieczki funkcjonalność Joiner i Splitter http://goo.gl/pfSCb – oluies

+0

@oluies: -O OscarRyz

Odpowiedz

21

Możesz go rozwiązać, używając negative look behind.

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

Zasadniczo mówi, podzielonego na każdym ", " że nie jest poprzedzone odwrotnym ukośnikiem.

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

wyjściowa:

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

(ideone.com link)


Jeśli zdarzy ci się być zatrzymany z non-uciekły wartości oddzielonych przecinkami, można wykonać następujące czynności (podobny) hack:

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

który mówi, podział na każdym ", " której następuje niektórych znaków słownych i an =

(ideone.com link)

+1

Dość interesująca odpowiedź, ale nie na pytanie "Jak mogę uciec od przecinka, więc nie pasuje do przecinków pośrednich? ' – Zeemee

+2

Ładne rozwiązanie, ale IMHO za zły problem. Podczas gdy taki ciąg może zostać sparsowany przy użyciu tego, pewnego dnia nie powiedzie się, gdy ktoś powie: 'type = simple, output = Hello, world, repeat = until tomorrow, a może until 0 = 1'. Proponuję odpowiedni mechanizm ucieczki, zamiast być zbyt inteligentnym. – maaartinus

+0

Dobra uwaga. Szczerze mówiąc, źle odczytałem pytanie. Zaktualizowano. – aioobe

0

myślę

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

powinno działać. Rozdzieli się na wszystkie przecinki, które nie są poprzedzone ukośnikiem odwrotnym. BTW, jeśli pracujesz z Eclipse, mogę polecić wtyczkę QuickRex do testowania i debugowania Regeksów.

+0

To jest prawie w porządku, ale nie doskonałe, ponieważ nie pozwala na ucieczkę ukośników odwrotnych. Zjedzie postać przed odwrotnym ukośnikiem. Powinien to zrobić lookbehind. – maaartinus

+0

Nie mam problemu z ucieczką z czymś innym: P Próbuję ... – OscarRyz

+1

@maaartinus: Tak, masz rację ... – Zeemee

4

Obawiam się, że nie ma idealne rozwiązanie dla String.split. Używanie matchera do trzech części działałoby.Jeśli liczba części nie jest stała, polecam pętlę z matcher.find. Coś takiego może

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

Prawdopodobnie będziesz chciał pominąć miejsca po przecinku, a także:

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

To naprawdę nie jest skomplikowane, po prostu pamiętać, że trzeba czterech backslashy w celu dopasowania jednego .

+0

+1 Ciągłe żucie, które ... – OscarRyz

+0

To proste: grupa jest sekwencją składającą się z 1. normalnych znaków (tj. Dowolnych z wyjątkiem ukośnika odwrotnego i przecinka) i 2. dowolnego znaku zbiegunowego (to znaczy ukośnika odwrotnego, po którym następuje dowolne). Pozostała część to przecinek lub końcowa kotwica. – maaartinus

+0

Jeśli przejdziesz trasą Pattern/Matcher, powinno być prostsze 'matcher.znaleźć rozwiązanie, które może znaleźć jedną parę klucz/wartość na raz, nie? – aioobe

2

Uciekając współpracuje z przeciwieństwo odpowiedź aioobe za (aktualizacja: aioobe teraz używa tego samego konstruktu, ale nie wiedziałem, że gdy to pisałem), ujemny lookbehind

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("\\,", ",") + "'"); 
} 

wyjściowa:

'type = proste'
'wyjście = Hello, world'
'repeate = true'

referencyjny: