2016-03-07 17 views
8

kullanarak bir dize
Java: (") Bir ayırıcı olarak virgül (,) kullanarak bir dize bölmek ve iç tırnak herhangi virgül görmezden zorunda Regex

fieldSeparator : ,
fieldGrouper : "

dize bölün bölünmeye geçerli: "1","2",3,"4,5"

şöyle bunu başarmak mümkün duyuyorum:

String record = "\"1\",\"2\",3,\"4,5\""; 
String[] tokens = record.split(",(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); 

Çıktı:

"1" 
"2" 
3 
"4,5" 

Şimdi meydan fieldGrouper (") bölünmüş jeton bir parçası olması gerektiğidir. Bunun için normal ifadeleri anlayamıyorum.

bölünmüş beklenen çıkışı:

1 
2 
3 
4,5 
+0

Ben this char-by-Char yaptığını düşünüyorum İşte

bir Java sample code olduğunu aslında daha okunabilir ve kesinlikle daha hızlı olacaktır. Ve algoritma aldığı kadar basit. Er ya da geç görünecek olan "" "istisnasının üstesinden gelmek daha kolaydır. – Dariusz

+0

Neden hatalı biçimlendirilmiş JSON girişiyle çalıştığınızı sorabilir miyiz? Alıntılar ile funkyness başa çıkmak için bu zor ve kaynak temizlemek için daha iyi olabilir. –

cevap

4

Güncelleme:

String[] tokens = record.split("(,*\",*\"*)");

Sonuç:
Image Link

Başlangıç ​​Çözüm:
(.split yöntemiyle @ çalışmıyor)

Bu RexEx desen istediğiniz bölümleri izole eder:
(?:\\")(.*?)(?:\\")

O kullanır olmayan yakalama çiftleri ayırmak için gruplar kaçtı tırnak işaretleri, ve aradaki her şeyi izole etmek için bir yakalama grubu.

Buradan kontrol edin: Live Demo

+2

Bu normal ifade, "3" ile veya "..." ile kapatılmamış diğer değerler ile eşleşmiyor. –

+0

@ WiktorStribiYeni Çözümü güncelledim ancak ilk çözümümde "#" deseninin tutarlı olduğunu varsaydım. '3'ün yakalanmadığını farketmedim ve hala @rvd'nin' 3 'için farklı bir biçime sahip olup olmadığını merak ediyorum. Her iki durumda da yeni çözüm işe yarıyor. – Enteleform

+0

Üzgünüz, ancak 1 ve 2 ayrı sayılar olduğunda ikinci solleksi 1,2 gibi giriş için çalışmayacaktır. –

0

Benim teklifim:

record = record.replaceAll("\",", "|"); 
record = record.replaceAll(",\\\"", "|"); 
record = record.replaceAll("\"", ""); 

String[] tokens = record.split("\\|"); 

for (String token : tokens) { 
    System.out.println(token); 
} 
2

Benim önerim:

"([^"]+)"|(?<=,|^)([^,]*) 

regex demo bakınız. Dizgiler gibi "..." ile eşleşecek ve sadece alıntılar arasında ne var olduğunu ve daha sonra , dışında bir karakter dizisinin başında veya bir virgülden sonra Grup 2 dizileri ile eşleşecek ve yakalayacaktır.

String s = "value1,\"1\",\"2\",3,\"4,5\",value2"; 
Pattern pattern = Pattern.compile("\"([^\"]+)\"|(?<=,|^)([^,]*)"); 
Matcher matcher = pattern.matcher(s); 
List<String> res = new ArrayList<String>(); 
while (matcher.find()){      // Run the matcher 
    if (matcher.group(1) != null) {   // If Group 1 matched 
     res.add(matcher.group(1));   // Add it to the resulting array 
    } else { 
     res.add(matcher.group(2));   // Add Group 2 as it got matched 
    } 
} 
System.out.println(res); // => [value1, 1, 2, 3, 4,5, value2] 
+0

Daha iyi bir öneri, onun IMHO kaynak verilerini temizlemesidir. –

1

ben geçici çözüm bu tür denemek istiyorum:

String record = "\"1\",\"2\",3,\"4,5\""; 
record = record.replaceAll("\"?(?<!\"\\w{1,9999}),\"?|\""," "); 
String[] tokens = record.trim().split(" "); 
for(String str : tokens){ 
    System.out.println(str); 
} 

Çıktı:

1 
2 
3 
4,5 
+0

Nihayetinde benzer bir geçici çözüm kullanmak zorundaydım, yani, ilk olarak bölme ve sonra her bir belirteçten alıntılar (varsa) kaldırın. – rvd

İlgili konular