2015-07-01 11 views
5

Przeczytałem ten ciąg z pliku:Jak podzielić ciąg przez regex java z tyłu?

abc | ABC (abc \ | abc) | def

Chcę uzyskać tablicę inludes 3 pozycji:

  1. abc
  2. ABC (ABC \ | abc)
  3. def

Jak poprawnie pisać wyrażenie regularne? line.split("(?!<=\\)\\|") nie działa.

+0

Jaki jest Twój stan rozłam? Czy jest to "|", które znajduje się wewnątrz nawiasu, lub '| które nie ma przed nim' '' '? Również twój ciąg może być 'abc \ | abc | (ab | ab) '? Lub nawet "ab \\ | ab \ | ab'? Jeśli tak, w jaki sposób chcesz go podzielić? – Pshemo

+0

wygląda na to, że potrzebujesz podzielić | postać. Jeśli tego chcesz, możesz po prostu użyć String [] splitedArray = str.split ("\\ |"); –

+0

@RamanShrivastava To nie jest takie proste. Również OP już dzieli się na '\\ |'. – Pshemo

Odpowiedz

2

Kod:

public class __QuickTester { 

    public static void main (String [] args) { 

     String test = "abc|abc (abc\\|abc)|def|banana\\|apple|orange"; 

     // \\\\ becomes \\ <-- String 
     // \\ becomes \ <-- In Regex 
     String[] result = test.split("(?<!\\\\)\\|"); 

     for(String part : result) { 
      System.out.println(part); 
     } 
    } 
} 

wyjściowa:

abc 
abc (abc\|abc) 
def 
banana\|apple 
orange 


Uwaga: Musisz \\\\ (4 backslashy), aby uzyskać \\ (2 backslashy) jako ciąg znaków, a następnie \\ (2 backslashes) staje się pojedynczym \ w Regex.

+0

Ale ciąg może inculde "abc | abc", aktualizuję mój post – mystdeim

+0

@mystdeim Bez spacji i działa! Myślę, że teraz jest poprawne. :) – Gosu

0

spróbować tej regex: ([\w()]|(\\|))+

0

Główny problem w swoim podejściu jest to, że \ jest wyjątkowy w regex, ale również w ciąg. Tak, aby utworzyć \ dosłowne trzeba uciec go dwukrotnie:

  • w regex \\
  • w String "\\\\".

więc trzeba by napisać go jako split("(?<!\\\\)\\|")

Ale są też możliwe problemy z tym podejściem od podziału na | który jest prosty poprzedzone \ mogą być podatne na błędy. Ponieważ używasz \ jako znaku specjalnego, aby utworzyć literał \, prawdopodobnie musisz napisać go jako \\, na przykład, aby utworzyć c:\foo\bar\, prawdopodobnie musisz zapisać go w swoim tekście jako c:\\foo\\bar\\.

Więc w takim razie powiedzmy, że chcesz podzielić tekst jak

abc|foo\|c:\\bar\\|cde 

Zakładam, że chcesz podzielić tylko w ten umieszcza

abc|foo\|c:\\bar\\|cde 
^   ^

ponieważ

  • w abc|foo rurka | nie ma przed sobą \,
  • w bar\\|cde mimo rury o \ przed nim, wiemy, że to nie był używany \ uciec |, ale wygenerować tekst reprezentujący \ dosłowny (tak ogólnie | które mają zakaz lub parzysta liczba \ znaki są OK, aby podzielić na).

Ale split(onEachPipeWhichHaveBackslashBeforeIt) jak split("(?<!\\\\)\\|") nie będzie podzielona między bar\\|cde ponieważ istnieje \ przed | który uniemożliwi takiego podziału.

Aby rozwiązać ten problem, można sprawdzić, czy istnieje nieparzysta liczba \ przed |, ale jest to trudne do zrobienia w Javie, ponieważ niedostateczna widoczność musi mieć ograniczoną szerokość.

Możliwe rozwiązanie to split("(?<!(?<!\\\\)((\\\\){2}){0,1000}\\\\)\\|") i założenie, że ciąg nigdy nie będzie zawierał więcej niż 1000 ciągłych znaków \, ale wydaje się, że jest przesadny.

IMO lepszym rozwiązaniem byłoby wyszukiwanie ciągów, które chcesz znaleźć, szukanie ciągów, które chcesz podzielić. I ciągi chcesz dowiedzieć się

  • wszystkie znaki oprócz |
  • wszystkie znaki, które są poprzedzone \ (w tym | od \ po prostu uciec).

Więc nasz regex mogłaby wyglądać (\\\\.|[^|])+ (umieściłem \\\\. na początku, aby zapobiec [^|] spożywania \ który będzie używany do ucieczki inne znaki).

Przykład:

Pattern p = Pattern.compile("(\\\\.|[^|])+"); 
Matcher m = p.matcher(text); 
while (m.find()){ 
    System.out.println(m.group()); 
} 

wyjściowa:

abc 
foo\|c:\\bar\\ 
cde 
Powiązane problemy