58

I can't figure out why the following code doesn't behave as expected

"Hello/You/There".replaceAll("/", "\\/");
  • Expected output: Hello\/You\/There
  • Actual output: Hello/You/There

Do I need to escape forward slashes? I didn't think so but I also tried the following against my will ... didn't work

"Hello/You/There".replaceAll("\\/", "\\/");

In the end I realized I don't need a regular expression and I can just use the following, which doesn't create a regular expression

"Hello/You/There".replace("/", "\\/");

However, I'd still like to understand why my first example doesn't work.

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • Can you show more context? Are you assigning the return result to a new string? Also, I don't think you need to escape it in the replacement string either. – David Harkness Mar 05 '12 at 22:43
  • You do have to escape the replacement :p ruakh's answer hit the nail on the head – Ruan Mendes Mar 05 '12 at 22:49

3 Answers3

90

The problem is actually that you need to double-escape backslashes in the replacement string. You see, "\\/" (as I'm sure you know) means the replacement string is \/, and (as you probably don't know) the replacement string \/ actually just inserts /, because Java is weird, and gives \ a special meaning in the replacement string. (It's supposedly so that \$ will be a literal dollar sign, but I think the real reason is that they wanted to mess with people. Other languages don't do it this way.) So you have to write either:

"Hello/You/There".replaceAll("/", "\\\\/");

or:

"Hello/You/There".replaceAll("/", Matcher.quoteReplacement("\\/"));

(Using java.util.regex.Matcher.quoteReplacement(String).)

ruakh
  • 175,680
  • 26
  • 273
  • 307
  • 3
    +1 And reading the Javadoc is no help either, as it implies it should work without the double-escape. – Jim Garrison Mar 05 '12 at 22:44
  • 1
    I did run across `Matcher.quoteReplacement` but didn't read enough of the documentation to realize that backslashes also must be escaped. – Ruan Mendes Mar 05 '12 at 22:56
  • You can see this link and the answer and comment threads to understand deeper about this. http://stackoverflow.com/questions/18875852/why-string-replaceall-in-java-requires-4-slashes-in-regex-to-actually-r/ – coder91 Sep 19 '13 at 11:55
  • 2
    @coder91: That question is actually about something different: it's about the well-known (and well-understood) fact that you need to double-escape certain things in the regex-string. This one is about the little-known (and more-surprising) fact that you also need to double-escape certain things in the replacement-string. – ruakh Sep 19 '13 at 15:33
  • Similarly to split a string by '/' you will need '\\/' as the splitter. – Ujjwal Singh Feb 12 '14 at 15:05
  • 1
    @UjjwalSingh: If your comment displayed how you meant it to, then -- that's not true. If your comment is missing some backslashes, then -- that's true, but not "similar". – ruakh Feb 12 '14 at 16:37
2

Double escaping is required when presented as a string.

Whenever I'm making a new regular expression I do a bunch of tests with online tools, for example: http://www.regexplanet.com/advanced/java/index.html

That website allows you to enter the regular expression, which it'll escape into a string for you, and you can then test it against different inputs.

James Oravec
  • 19,579
  • 27
  • 94
  • 160
-1

There is actually a reason behind why all these are messed up. A little more digging deeper is done in this thread and might be helpful to understand the reason why "\\" behaves like this.

Community
  • 1
  • 1
coder91
  • 51
  • 3
  • 1
    Not really, I know I have to escape backslashes in JAVA, and that I have to double escape them in a JAVA regex, but the real problem is that single escaping should be enough in the replacement string since that's not a regex and the \ is not a special character – Ruan Mendes Sep 19 '13 at 16:05