8

In my java code, if a string input has got any of the special characters mentioned, that should get preceded by \\

Special character set is {+, -, &&, ||, !, (, ), {, },[, ], ^, "", ~, *, ?, :, \}. I tried using String.replaceAll(old,new) but to my surprise its not working, even though I am giving proper values for 'old' and 'new'.

if old=":",new="\:"

I put the special chars in a String array, iterated it in a for loop, checked whether it is present in the string, if yes, input.replaceAll(":","\\:"). But its not giving me the intended output. Please help

String[] arr = { "+", "-", "&&", "||", "!", "(", ")", "{", "}",
                "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "AND", "OR" };

    for (int i = 0; i < arr.length; i++) {
//'search' is my input string

        if (search.contains((String) arr[i])) {

            String oldString = (String) arr[i];

            String newString = new String("\\" + arr[i]);
            search = search.replaceAll(oldString, newString);
            String newSearch = new String(search.replaceAll(arr[i],
                    newString));


        }
    }
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
Cheese
  • 245
  • 2
  • 3
  • 9

4 Answers4

14

Once you realise replaceAll takes a regex, it's just a matter of coding your chars as a regex.

Try this:

String newSearch = search.replaceAll("(?=[]\\[+&|!(){}^\"~*?:\\\\-])", "\\\\");

That whacky regex is a "look ahead" - a non capturing assertion that the following char match something - in this case a character class.

Notice how you don't need to escape chars in a character class, except a ] (even the minus don't need escaping if first or last).

The \\\\ is how you code a regex literal \ (escape once for java, once for regex)


Here's a test of this working:

public static void main(String[] args) {
    String search = "code:xy";
    String newSearch = search.replaceAll("(?=[]\\[+&|!(){}^\"~*?:\\\\-])", "\\\\");
    System.out.println(newSearch);
}

Output:

code\:xy
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • You also need to escape `[`. – Rohit Jain Dec 04 '12 at 05:37
  • @RohitJain no you don't need to escape `[`. Try it – Bohemian Dec 04 '12 at 06:31
  • @Bohemian.. Tried it, that's why I posted the comment. It's not working. – Rohit Jain Dec 04 '12 at 06:32
  • @RohitJain I want to see this for myself! I can't check now (using iPhone) but will check ASAP. I was sure you didn't, but I keep learning stuff here – Bohemian Dec 04 '12 at 06:36
  • @RohitJain Thanks Bohemian and Rohit. When I used this it gave an unclosed character class exception, so [ should be escaped right?Also if any of the symbol is present in my string that should be replaced with an escape followed by that symbol itself, how to achieve that using this pattern?How to get that group value to be appended with "\\" in java. I tried for an input like a*b, but it failed. I will verify it again and will let you know – Cheese Dec 13 '12 at 09:49
  • When I tried for an input string code:xy it failed giving StringIndexOutOfBoundsException at String newSearch = search.replaceAll("(?=[-+&|!(){}[\\]^\"~*?:\\\\])", "\\"); java.lang.StringIndexOutOfBoundsException: String index out of range: 1 at java.lang.String.charAt(String.java:686) at java.util.regex.Matcher.appendReplacement(Matcher.java:703) at java.util.regex.Matcher.replaceAll(Matcher.java:813) at java.lang.String.replaceAll(String.java:2189) – Cheese Dec 13 '12 at 10:18
  • Pattern p = Pattern.compile("(.*)(?=[-+&|!(){}\\[\\]^\"~*?:\\\\])(.*)"); Matcher m = p.matcher(search); String s0 = m.group(0); String s1 = m.group(1); String s2 = m.group(2); Now for code:xy, s0=code:xy, s1=code and s2=:xy. So I need to get like this and should append that with \\ while using replaceAll() right? – Cheese Dec 13 '12 at 11:23
  • @user1863118 OK I fixed the problem. It took me a while to realise that I needed to double-escape the *replacement* backslash ie `\\\\ ` See edited answer, including some testing code to show that it *does* in fact work :) – Bohemian Dec 13 '12 at 19:05
  • Invalid escape sequence in JSON string '\:' – Dean Peterson Oct 14 '17 at 18:05
  • @Dean then try removing the colon `:` from the regex. – Bohemian Oct 15 '17 at 00:11
3

String#replaceAll takes a regex as first parameter. So, your code will fail if the input in the string is a meta-character like - +.

You should use String#replace.

And also you don't need the last assignment: -

String newSearch = new String(search.replaceAll(arr[i], newString));

As, you are not using it at all. You are in fact assigning the modified string back to search, so it's not required.

Also, rather than using new String(...), to build your new string. In fact, you just need a single line in your if-statement.

Ok now, after that explanation, you can now use the below for-loop: -

for (int i = 0; i < arr.length; i++) {
    if (search.contains(arr[i])) {
        search = search.replace(arr[i], "\\" + arr[i]);
    }
}
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
  • Thanks Rohit. And inorder to use replace instead of replaceAll, I have to loop over my input string,making that the outer loop and this one the inner loop right. I thought to avoid iterating the input string(thinking of cases when input string length gets large!).Also there are some symbols that cannot be escaped with a single '\' right...like for \ itself, we need to escape it as '\\\\' right? – Cheese Dec 13 '12 at 09:33
  • @Rohit, am getting help from you more than 4 years, thanks for being active helper! – sunleo Jun 20 '17 at 10:50
2

Try to use the below one. Please use replace method instead of ReplaceAll

search = search.replace(oldString, newString);

Kaliappan
  • 642
  • 9
  • 24
0

when I tried the code below it worked

String[] arr = { "+", "-", "&&", "||", "!", "(", ")", "{", "}",
                    "[", "]", "^", "\"", "~", "*", "?", ":", "\\", "AND", "OR" };

        for (int i = 0; i < arr.length; i++) {
    //'search' is my input string

            if (search.contains((String) arr[i])) {

                String oldString = (String) arr[i];

                String newString = new String("\\" + arr[i]);
                search = search.replaceAll(oldString,(String) ("\\" + newString));



            }
        }
Cheese
  • 245
  • 2
  • 3
  • 9