2010-10-06 9 views
9

łańcuch zostanie podzielonaDzielenie ciąg znaków, który musi uciec sekwencji przy użyciu wyrażenia regularnego w Javie

abc:def:ghi\:klm:nop 

String powinny być podzielone na podstawie „:” „\” jest ucieczka charakter. Tak więc "\:" nie powinno być traktowane jako token.

split (":") daje

[abc] 
[def] 
[ghi\] 
[klm] 
[nop] 

Wymagane wyjście jest array of string

[abc] 
[def] 
[ghi\:klm] 
[nop] 

jaki sposób \: być ignorowane

+0

Możliwe są również następujące: "abc:" def: ghi ": jkl'? –

Odpowiedz

16

użyć look-behind assertion:

split("(?<!\\\\):") 

Będzie to zgodne tylko wtedy, gdy nie ma poprzedzających \. Korzystanie podwójne ucieczce \\\\ jest wymagany jako jedna jest wymagane dla deklaracji strun i jeden dla wyrażenia regularnego.

jednak pamiętać, że to nie będzie można uciec backslashy, w przypadku, gdy chcesz zezwolić token do końca z odwrotnym ukośnikiem. Aby to zrobić trzeba będzie najpierw wymienić wszystkie podwójne backslashy z

string.replaceAll("\\\\\\\\", ESCAPE_BACKSLASH) 

(gdzie ESCAPE_BACKSLASH jest ciągiem znaków, które nie wystąpią w swoim wejściu), a następnie, po rozdzieleniu z użyciem twierdzenia wygląd z opóźnieniem, należy wymienić łańcuch ESCAPE_BACKSLASH z backslash przed zmianą z

token.replaceAll(ESCAPE_BACKSLASH, "\\\\") 
0

Gumbo był tuż za pomocą look-behind assertion, ale w przypadku, gdy ciąg zawiera uciekł znak ucieczki (np \\) tuż przed przecinkiem, podział może pęknąć. Zobacz ten przykład:

test1\,test1,test2\\,test3\\\,test3\\\\,test4

Jeśli tak prosty look-tył podział na (?<!\\), jako sugerowanej Gumbo, łańcuch zostanie podzielony na dwie części tylko test1\,test1 i test2\\,test3\\\,test3\\\\,test4. Dzieje się tak dlatego, że obserwatorzy po prostu sprawdzają jedną postać z powrotem dla postaci ucieczki. Co właściwie byłoby poprawne, jeśli łańcuch jest podzielony na przecinki i przecinki poprzedzone parzystą liczbą znaków ewakuacyjnych.

Aby to osiągnąć nieco bardziej skomplikowane (podwójne) look-za potrzebne jest wyrażenie:

(?<!(?<![^\\]\\(?:\\{2}){0,10})\\),

Używając tego bardziej skomplikowanego wyrażenia regularnego w Javie, znowu wymaga uciec wszystko \ przez \\. Tak to powinno być bardziej wyrafinowany odpowiedź na pytanie:

"any comma separated string".split("(?<!(?<![^\\\\]\\\\(?:\\\\{2}){0,10})\\\\),"); 

Uwaga: Java nie obsługuje nieskończone powtórzeń wewnątrz lookbehinds. Dlatego tylko do 10 powtarzających się znaków podwójnych ewakuacyjnych są sprawdzane za pomocą wyrażenia {0,10}. W razie potrzeby można zwiększyć tę wartość, dostosowując drugą wartość.

Powiązane problemy