Java: dzielenie ciągu znaków oddzielonych przecinkami, ale ignorowanie przecinków w cudzysłowach
Mam sznurek trochę podobny do tego:
foo,bar,c;qual="baz,blurb",d;junk="quux,syzygy"
Chcę to oddzielić przecinkami - ale muszę zignorować przecinki w cudzysłowie. W jaki sposób mogę to zrobić? Wygląda na to, że podejście regexp nie działa; Przypuszczam, że mogę ręcznie skanować i wejść w inny tryb, gdy widzę cytat, ale byłoby miło skorzystać z bibliotek, które już istnieją. (
edit
: Myślę, że chodziło mi o biblioteki, które są już częścią JDK lub częścią powszechnie używanych bibliotek, takich jak Apache Commons).
powyższa linia powinna zostać podzielona na:
foo
bar
c;qual="baz,blurb"
d;junk="quux,syzygy"
Uwaga:
NIE jest to plik CSV, jest to jedna linia zawarta w pliku o większej ogólnej strukturze
Nie znaleziono powiązanych wyników
Zaproszony:
Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się
11 odpowiedzi
Anonimowy użytkownik
Potwierdzenie od:
Wyjście:
Innymi słowy:
dziel na przecinek tylko wtedy, gdy przed przecinkiem znajduje się zero lub parzysta liczba cudzysłowów
.
Lub trochę bardziej przyjazne dla oka:
co daje to samo, co w pierwszym przykładzie.
EDIT
>
Jak wspomniał @MikeFHay w komentarzach:
Wolę używać
rozdzielacz guawy
http://docs.guava-libraries.go ... .html
ponieważ ma bardziej rozsądne wartości domyślne (zobacz dyskusję powyżej na temat pustych dopasowań obciętych przez , więc zrobiłem to:
Anonimowy użytkownik
Potwierdzenie od:
Jeśli nie zależy Ci na zachowaniu przecinków w cudzysłowach, możesz uprościć to podejście (bez obsługi indeksu początkowego, bez specjalnych przypadków
ostatni znak
), zastępując cytowane przecinki czymś innym, a następnie oddzielając je przecinkami:
Anonimowy użytkownik
Potwierdzenie od:
http://sourceforge.net/projects/javacsv/
/
https://github.com/pupi1985/JavaCSV-Reloaded
https://github.com/pupi1985/JavaCSV-Reloaded
(rozwidlenie poprzedniej biblioteki, która pozwoli wygenerowanym wynikom mieć terminatory linii Windows , gdy nie jest uruchomiony system Windows)
http://opencsv.sourceforge.net
http://opencsv.sourceforge.net/
/
CSV API dla Java
https://coderoad.ru/101100/
Czy możesz polecić bibliotekę Java do czytania (i ewentualnie pisania) plików CSV?
https://coderoad.ru/200609/
Biblioteka Java lub aplikacja do konwersji pliku CSV do pliku XML?
https://coderoad.ru/123/
Anonimowy użytkownik
Potwierdzenie od:
Moje rozwiązanie i test znajdują się poniżej.
Oczywiście możesz zmienić przełącznik na else-ifs w tym fragmencie, jeśli nie czujesz się komfortowo z jego brzydotą. Zauważ, że po przełączniku separatora nie ma przerwy. Technologia StringBuilder została wybrana zamiast StringBuffer zgodnie z projektem, aby zwiększyć prędkość tam, gdzie bezpieczeństwo wątków nie ma znaczenia.
Anonimowy użytkownik
Potwierdzenie od:
Szukaj
http://www.regular-expressions ... .html
wygląda jak . Musi pasować do, które nie jest otoczone przez .
Anonimowy użytkownik
Potwierdzenie od:
Jeśli prawdopodobnie wkrótce będziesz potrzebować dużej złożoności, poszukałbym biblioteki parsera. Na przykład tutaj
to
http://www.javaworld.com/javaw ... .html
Anonimowy użytkownik
Potwierdzenie od:
(Ćwiczenie dla czytelnika: rozszerz swoją pracę o cudzysłowy, szukając również odwrotnych ukośników.)
Anonimowy użytkownik
Potwierdzenie od:
Wzorzec ma dwie możliwości: ciąg w cudzysłowie (
"[^"] * "
lub ) lub wszystko aż do następnego przecinka ([ ^,] +
). aby obsługiwać puste komórki, musimy pozwolić, aby element niecytowany był pusty i użyć następującego przecinka, jeśli jest obecny, a także użyć kotwicy :Pattern p = Pattern.compile("\\G\"(.*?)\",?|([^,]*),?");
Szablon zawiera również dwie grupy przechwytywania służące do pobierania zawartości ciągu znaków w cudzysłowie lub zwykłej zawartości.
Następnie w Javie 9 możemy pobrać tablicę jako
podczas gdy starsze wersje Java potrzebują pętli, takich jak
Dodanie elementów do lub tablicy pozostaje jako podatek akcyzowy dla czytelnika.
W przypadku języka Java 8 możesz użyć implementacji
ta odpowiedź
https://stackoverflow.com/a/37482157/2711488
zrobić to podobnie do rozwiązania Java 9.
W przypadku mieszanej treści z wbudowanymi ciągami znaków, jak w pytaniu, możesz po prostu użyć
Pattern p = Pattern.compile("\\G((\"(.*?)\"|[^,])*),?");
Ale wtedy ciągi znaków są przechowywane w cudzysłowach.
Anonimowy użytkownik
Potwierdzenie od:
Po oddzieleniu przecinkiem zamień wszystkie dopasowane identyfikatory na oryginalne wartości ciągu.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od: