24

I need to escape all quotes (') in a string, so it becomes \'

I've tried using replaceAll, but it doesn't do anything. For some reason I can't get the regex to work.

I'm trying with

String s = "You'll be totally awesome, I'm really terrible";
String shouldBecome = "You\'ll be totally awesome, I\'m really terrible";
s = s.replaceAll("'","\\'"); // Doesn't do anything
s = s.replaceAll("\'","\\'"); // Doesn't do anything
s = s.replaceAll("\\'","\\'"); // Doesn't do anything

I'm really stuck here, hope somebody can help me here.

Thanks,

Iwan

Iwan Eising
  • 291
  • 1
  • 2
  • 7
  • possible duplicate of [replace() and replaceAll() in Java](http://stackoverflow.com/questions/12941266/replace-and-replaceall-in-java) – user2864740 Dec 13 '13 at 00:54
  • In case you haven't considered this yet, if the input is from a user in any way, you might also want to replace any backslashes with double backslashes first. Like if the user enters `"You are 'awesome'\'amazing'"`, then you currently would get `"You are \'awesome\'\\'amazing\'"`. That leaves the 3rd quote unescaped because that user-entered backslash is escaping the generated backslack after it! – tobii Dec 21 '13 at 19:30

6 Answers6

31

You have to first escape the backslash because it's a literal (yielding \\), and then escape it again because of the regular expression (yielding \\\\). So, Try:

 s.replaceAll("'", "\\\\'");

output:

You\'ll be totally awesome, I\'m really terrible
user2864740
  • 60,010
  • 15
  • 145
  • 220
Sage
  • 15,290
  • 3
  • 33
  • 38
  • 3
    Matcher.quoteReplacement("\\'") can be used to quote the replacement string. – isnot2bad Dec 12 '13 at 23:11
  • 2
    @isnot2bad I really think the usage of `Matcher.quoteReplacement` almost deserves an answer itself. (It is `quoteReplacement`, not `quoteRegex` for reason.) – user2864740 Dec 12 '13 at 23:21
  • @user2864740, could you please elaborate a little. I have explained it in terms of replace function character sequence as for this case we would not need four backslash but only two as `Nambari` answered. – Sage Dec 12 '13 at 23:57
  • 1
    My complaint is with ".. because of the regular expression ..", which is wrong. It is a [replacement string](http://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#replaceAll(java.lang.String)), not a regular expression. – user2864740 Dec 13 '13 at 00:37
  • @user2864740, yes but what i meant is that to be replaced with this regular expression of `replaceAll` we will need to re-escape it – Sage Dec 13 '13 at 00:40
  • The *regular expression* is denoted by the string literal `"'"`. The method isn't a regular expression, but it *uses* a regular expression. – user2864740 Dec 13 '13 at 00:41
  • Can you please tell me what to do if I have to replace `"` with `\"` ? – Girdhari Agrawal Aug 11 '16 at 09:50
  • this is not working please suggest some other method – Dinesh Pathak DK Oct 23 '18 at 11:23
12

Use replace()

 s = s.replace("'", "\\'"); 

output:

You\'ll be totally awesome, I\'m really terrible

coding_idiot
  • 13,526
  • 10
  • 65
  • 116
kosa
  • 65,990
  • 13
  • 130
  • 167
10

Let's take a tour of String#repalceAll(String regex, String replacement)

You will see that:

An invocation of this method of the form str.replaceAll(regex, repl) yields exactly the same result as the expression

Pattern.compile(regex).matcher(str).replaceAll(repl)

So lets take a look at Matcher.html#replaceAll(java.lang.String) documentation

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.

You can see that in replacement we have special character $ which can be used as reference to captured group like

System.out.println("aHellob,aWorldb".replaceAll("a(\\w+?)b", "$1"));
// result Hello,World

But sometimes we don't want $ to be such special because we want to use it as simple dollar character, so we need a way to escape it.
And here comes \, because since it is used to escape metacharacters in regex, Strings and probably in other places it is good convention to use it here to escape $.

So now \ is also metacharacter in replacing part, so if you want to make it simple \ literal in replacement you need to escape it somehow. And guess what? You escape it the same way as you escape it in regex or String. You just need to place another \ before one you escaping.

So if you want to create \ in replacement part you need to add another \ before it. But remember that to write \ literal in String you need to write it as "\\" so to create two \\ in replacement you need to write it as "\\\\".


So try

s = s.replaceAll("'", "\\\\'");

Or even better

to reduce explicit escaping in replacement part (and also in regex part - forgot to mentioned that earlier) just use replace instead replaceAll which adds regex escaping for us

s = s.replace("'", "\\'");
Pshemo
  • 122,468
  • 25
  • 185
  • 269
4

This doesn't say how to "fix" the problem - that's already been done in other answers; it exists to draw out the details and applicable documentation references.


When using String.replaceAll or any of the applicable Matcher replacers, pay attention to the replacement string and how it is handled:

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.

As pointed out by isnot2bad in a comment, Matcher.quoteReplacement may be useful here:

Returns a literal replacement String for the specified String. .. The String produced will match the sequence of characters in s treated as a literal sequence. Slashes (\) and dollar signs ($) will be given no special meaning.

Alan Moore
  • 73,866
  • 12
  • 100
  • 156
user2864740
  • 60,010
  • 15
  • 145
  • 220
1

You could also try using something like StringEscapeUtils to make your life even easier: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringEscapeUtils.html

s = StringEscapeUtils.escapeJava(s);
LeoPleurodon
  • 295
  • 3
  • 11
0

You can use apache's commons-text library (instead of commons-lang):

Example code:

org.apache.commons.text.StringEscapeUtils.escapeJava(escapedString);

Dependency:

compile 'org.apache.commons:commons-text:1.8'

OR

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-text</artifactId>
   <version>1.8</version>
</dependency>
Bogdan Kobylynskyi
  • 1,150
  • 1
  • 12
  • 34