2009-02-12 5 views
25

Sprzątam przychodzący tekst w moim kodzie Java. Tekst zawiera dużo "\ n", ale nie jak w nowej linii, ale dosłownie "\ n". Używałem replaceAll() z klasy String, ale nie byłem w stanie usunąć "\ n". nie wydają się działać:Czyszczenie i zamiana tekstu: usuń n z tekstu w Javie

String string; 
string = string.replaceAll("\\n", ""); 

Ani robi to:

String string; 
string = string.replaceAll("\n", ""); 

Chyba ten ostatni jest identyfikowany jako rzeczywisty nowej linii, więc wszystkie nowe linie z tekstem byłoby oddalony.

Również, jaki byłby skuteczny sposób usuwania różnych wzorów niewłaściwego tekstu z ciągu. Używam wyrażeń regularnych do ich wykrywania, takich jak znaki zastrzeżone HTML itp. I replaceAll, ale za każdym razem, gdy używam replaceAll, cały ciąg jest odczytywany, prawda?

UPDATE: Dzięki za twoje wspaniałe odpowiedzi. I zostały rozszerzone na to pytanie tutaj:
Text replacement efficiency
pytam konkretnie o wydajności: D

+0

były starasz się dosłownie usunąć wszystkie wystąpienia „\ n”, czy jesteś próbuje usunąć nowe znaki kontrolne linii? Myślę, że to zmieni regex – mmcrae

Odpowiedz

43

Hooknc ma rację. Chciałbym po prostu trochę wyjaśnić:

"\\ n" tłumaczy się na "\ n" po kompilacji (od ucieczki od ukośnika odwrotnego). Tak więc silnik regex widzi "\ n" i myśli nową linię, i usunie te (a nie dosłowne "\ n", które masz).

"\ n" tłumaczy się na prawdziwą nową linię przez kompilator. Tak więc nowy znak linii jest wysyłany do silnika regex.

"\\\\ n" jest brzydki, ale prawda. Kompilator usuwa sekwencje specjalne, więc silnik wyrażeń widzi "\\ n". Silnik regex widzi dwa odwrotne ukośniki i wie, że pierwszy z nich ucieka, co przekłada się na sprawdzanie literalnych znaków "\" i "n", dając pożądany rezultat.

Java jest fajna (to język, w którym pracuję), ale myślenie o zasadzie podwójnego ucieczki z regexów może być prawdziwym wyzwaniem.Dla dodatkowej zabawy wygląda na to, że StackOverflow lubi również tłumaczyć ukośniki.

+2

Dobre wyjaśnienie. Chciałbym również dodać, że wiele osób zapomina, że ​​pierwszy argument w String.replaceAll() jest wyrażeniem regularnym, a nie literalnym. –

+0

Czy istnieje różnica między wysyłaniem "\ n" lub nowym znakiem linii do silnika regex? Oba wydają się mieć takie same wyniki. – ADTC

22

Chyba trzeba dodać jeszcze kilka slashies ...

String string; 
string = string.replaceAll("\\\\n", ""); 

Objaśnienie: liczba slashów ma związek z tym, że "\ n" samo w sobie jest kontrolowaną postacią w Javie.

Aby uzyskać prawdziwe znaki "\ n", musimy użyć "\ n". Którego, jeśli wydrukowano by nam: "\"

Zamierzasz zastąpić wszystkie "\ n" w swoim pliku. Ale nie chcesz zastąpić kontrolki "\ n". Więc spróbowałeś "\ n", który zostanie przekształcony w znaki "\ n". Świetnie, ale może nie tak bardzo. Domyślam się, że metoda replaceAll stworzy teraz Wyrażenie regularne, używając teraz znaków "\ n", które zostaną błędnie odczytane jako znak kontrolny "\ n".

Uff, prawie gotowe.

Użycie replaceAll ("\\ n", "") najpierw konwertuje "\\ n" -> "\ n", które będą używane przez wyrażenie regularne. "\ N" zostanie użyte w wyrażeniu regularnym i faktycznie będzie reprezentować twój tekst "\ n". Właśnie tego chcesz zastąpić.

+0

Dzięki za odpowiedź. Czy istnieje wytłumaczenie tak wielu wycinków? –

+0

Edytowane w celu dodania wyjaśnienia. – hooknc

+0

Jestem zdezorientowany ... Nie mogłem go uruchomić dopóki nie użyłem 3 '\' w 'replaceAll()' dla 'String before =" this \ nhere ";' – mmcrae

11

Zamiast String.replaceAll(), która korzysta z wyrażeń regularnych, możesz być lepiej używać String.replace(), który wykonuje proste zastępowanie ciągu (jeśli używasz co najmniej Java 1.5).

String replacement = string.replace("\\n", ""); 

powinien zrobić, co chcesz.

+0

Prawdopodobnie także szybciej. –

+0

Dobry pomysł. Po prostu unikaj całej analizy składniowej i ucieczki, ponieważ jej nie używasz. – MBCook

+0

Świetnie, dzięki.Używam tego dla \ n, ale replaceAll dla innych wzorców, takich jak znaczniki HTML i zastrzeżone znaki. Jeśli masz jakieś wskazówki na temat większej efektywności zamiast powtarzania replaceAll dla każdego wzoru, byłoby to znacznie cenione. –

1

Inne odpowiedzi w wystarczającym stopniu opisują, jak to zrobić z replaceAll, i jak trzeba uciec od ukośników w razie potrzeby.

Od 1.5. Istnieje również String.replace(CharSequence, CharSequence), który wykonuje dosłowne zastępowanie ciągu znaków. Może to znacznie uprościć wiele problemów związanych z zastępowaniem ciągów znaków, ponieważ nie ma potrzeby ucieczki od metaznaków z wyrażeń regularnych, takich jak: ., i tak,, i sam.

Tak więc, biorąc pod uwagę ciąg znaków, który może zawierać podciąg "\n" (nie '\n'), możemy usunąć je w następujący sposób:

String before = "Hi!\\n How are you?\\n I'm \n good!"; 
System.out.println(before); 
// Hi!\n How are you?\n I'm 
// good! 

String after = before.replace("\\n", ""); 

System.out.println(after); 
// Hi! How are you? I'm 
// good! 

Zauważ, że jeśli nalegać na użyciu replaceAll, można zapobiec brzydotę za pomocą Pattern.quote:

System.out.println(
    before.replaceAll(Pattern.quote("\\n"), "") 
); 
// Hi! How are you? I'm 
// good! 

należy również używać Pattern.quote kiedy dostaniemy dowolny ciąg znaków, który musi być dopasowany dosłownie zamiast jako wzorcu wyrażenia regularnego.

2

Spróbuj tego. Mam nadzieję, że to pomoże.

raw = raw.replaceAll("\t", ""); 
raw = raw.replaceAll("\n", ""); 
raw = raw.replaceAll("\r", ""); 
0

Normalnie \ n działa poprawnie. W przeciwnym razie możesz wybrać wiele instrukcji replaceAll. najpierw zastosuj jeden replaceAll w tekście, a następnie ponownie zastosuj replaceAll w tekście. Powinno zrobić to, czego szukasz.

-2

Wierzę, że replaceAll() to kosztowna operacja. Poniższy rozwiązanie będzie prawdopodobnie działać lepiej:

String temp = "Hi \n Wssup??";   
System.out.println(temp); 

StringBuilder result = new StringBuilder(); 

StringTokenizer t = new StringTokenizer(temp, "\n"); 

while (t.hasMoreTokens()) { 
    result.append(t.nextToken().trim()).append(""); 
} 
String result_of_temp = result.toString(); 

System.out.println(result_of_temp); 
+0

To spasowanie nie robi tego, co chciał OP. – Pops

1

Użyłem tego rozwiązania, aby rozwiązać ten problem:

String replacement = str.replaceAll("[\n\r]", ""); 
3
string = string.replaceAll(""+(char)10, " ");