tags:

views:

304

answers:

4

I am using Matcher.appendReplacement() and it worked great until my replacement string had a $2 in it:

Note that backslashes ( \ ) and dollar signs ($) in the replacement string may cause the results to be different than if it were being treated as a literal replacement string. Dollar signs may be treated as references to captured subsequences as described above, and backslashes are used to escape literal characters in the replacement string.

Is there a convenience method somewhere that will escape all backslashes \ and dollar signs $ with a backslash? Or do I have to write one myself? It sounds like it's not that hard, just would be nice if they gave you one >:(

edit: since they do give you one, I need to replace(">:(", ":-)");

A: 

Looks like a duplicate of http://stackoverflow.com/questions/60160/how-to-escape-text-for-regular-expression-in-java to me.

daveb
Not that one. That question relates to the regex pattern string rather than the replacement. You could have added that answer as a comment, btw.
Tom Hawtin - tackline
+3  A: 

Use Matcher.quoteReplacement on the replacement string.

Unfortunately "ease of use" in this case conflicts with strong typing. [Explanation: An object of Java static type java.lang.String is any immutable sequence of chars. It doesn't tell you the format of that raw data. In this scenario we have text probably meaningful to the user, text encoded in a mini-language for replacement and text encoded in a mini-language for the pattern. The Java type system has no way of distinguishing these (although you can do fun things with annotation-based type checkers, often to avoid XSS or SQL/command injection vulnerabilities). For the pattern mini-language you can to a form of conversion with Pattern.compile although that is a specific use and most APIs methods ignore it (for ease of use). An equivalent ReplacementText.compile could be written. Further, you could ignore the mini-languages and go for libraries as "DSLs". But all this doesn't help casual ease of use.]

Tom Hawtin - tackline
Hey, all right! How did I miss that from the Javadoc?!?!?!?!!
Jason S
Very easily done.
Tom Hawtin - tackline
"Unfortunately "ease of use" in this case conflicts with strong typing." how so?
Jason S
Yeah.. could you clarify what the "ease of use / strong typing" note means?
Jonik
+1  A: 

I got it to work with the following, but I like Tom Hawtin's solution better :-)

private static Pattern escapePattern = Pattern.compile("\\$|\\\\");
replacement = escapePattern.matcher(replacement).replaceAll("\\\\$0");
matcher.appendReplacement(stringbuffer, replacement);

Tom's solution:

matcher.appendReplacement(stringbuffer, Matcher.quoteReplacement(replacement));
Jason S
+2  A: 

Here's another option:

matcher.appendReplacement(stringbuffer, "");
stringbuffer.append(replacement);

appendReplacement() handles the job of copying over the text between the matches, then StringBuffer#append() adds your replacement text sans adulterations. This is especially handy if you're generating the replacement text dynamically, as in Elliott Hughes' Rewriter.

Alan Moore