Wieso entsteht hier eine java.util.regex.PatternSyntaxException?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Weil ( ebenfalls in Regex eine Spezielle Bedeutung hat. Genauso wie das | in deiner Letzten Frage.

Du musst es wieder escapen mit "\\(".

Alle Zeichen, die in Regex eine Spezielle Bedeutung haben, musst du mit einem \\ escapen. Sollten diese sein: +*?(){}[].

ThoraxL 
Fragesteller
 14.08.2020, 17:52

Hmmm habe ich bereits korrigiert; aber wieso hier auch:

keyword = keyword.replaceAll("/\\/\\", "m");

MrAmazing2  14.08.2020, 17:57
@ThoraxL

Weil Java das \\/ dann umwandelt zu einem \/ und es an Regex weitergibt.

Und Regex sieht dann, dass da steht \/, und denkt sich: Diesen Escape Character gibts garnicht!

Was genau willst du damit Replacen? Ein /\/\ ?

MrAmazing2  14.08.2020, 17:59
@ThoraxL

Ganz einfach:

In Regex muss dafür \\ stehen. Weil Regex das dann zu einem \ Umwandelt.

Heißt in Java muss dafür \\\\ stehen.

keyword = keyword.replaceAll("/\\\\/\\\\", "m");
ThoraxL 
Fragesteller
 14.08.2020, 18:00
@MrAmazing2

Ok, da hätet ich auch drauf kommen können ,aber danke!

MrAmazing2  14.08.2020, 18:02
@ThoraxL

Beachte, dass das \ im String auch escaped sein muss, weil es sonst auch da eine Extra-Bedeutung hat! Siehe dick markiertes Beispiel. \n ist dir ja sicherlich bekannt. Java denkt hinter dem \ kommt irgend ein Buchstabe der für ne Anweisung steht. Deswegen Doppel-Backslash, damit java weiß, du willst da wirklich n backslash.

String str = "ab/\\/\\d"; //Wenn du das hier printest kriegst du ein "ab/\/\d"

str = str.replaceAll("/\\\\/\\\\","c");

= abcd.

Die Signatur der Methode replaceAll sieht wie folgt aus:

replaceAll​(String regex, String replacement)

Der Name des ersten Parameters (sowie die API Referenz) verraten es schon: Ein regulärer Ausdruck wird erwartet. Und in diesem hat die Klammer eine spezielle Bedeutung. Sie dient der Gruppierung von Ausdrücken. So könnte man bestimmte Teile eines Strings herausfiltern:

String text = "Simon goes to the street.";
String pattern = "Simon goes to the ([a-z]+).";

Wenn man nun nach Übereinstimmungen (Matches) sucht, werden auch die gefundenen Groups ermittelt. Dies wäre zum einen der komplette Match, als auch folgend die gruppierten Ausdrücke (oben: street). Auf jede Group kann man referenzieren und auf diese Weise bspw. Textersetzungen vornehmen. Lies Weiteres dazu bspw. hier.

Du solltest für deinen Fall also entweder das Zeichen maskieren:

keyword.replaceAll("\\(", "c");

oder viel besser, eher die replace-Methode verwenden. Sie ersetzt ebenso alle Vorkommen.

ThoraxL 
Fragesteller
 14.08.2020, 17:55

Hmmm habe ich bereits korrigiert; aber wieso hier auch:

keyword = keyword.replaceAll("/\\/\\", "m");

regex9  14.08.2020, 18:10
@ThoraxL

Aus /\\/\\ wird /\/\, womit der Parser für den regulären Ausdruck nichts anfangen kann. Du musst doppelt maskieren: /\\\\/\\\\.

Ich glaube, Java denkt, dass "(" kein String sein soll, sondern ein ", ein ( und ein ".

Versteng, was ich meine?

ThoraxL 
Fragesteller
 14.08.2020, 16:25

Nein - wieso ist die Klammer zu kein String für Java? Oder denkt Java es sei dann:

"(," oder was meintest du mit dem Letzten Teil?

LG Thorax