Manish Kumar
Manish Kumar

Reputation: 10502

Escape a character with backslash

I have some set of reserved keyword:

+ - && || ! ( ) { } [ ] ^ " ~ * ? : \ /

If any of these character is found in a string it should be escaped with a leading backslash e.g for string (1+1)=2

output should be \(1\+1\)=2

How can i do that in java?

Upvotes: 0

Views: 181

Answers (5)

Erwin Bolwidt
Erwin Bolwidt

Reputation: 31279

Considering your clarification that you want && to become \&& and || to become \||, this code will help you:

    String input = "blah && foo + 5 || lala & 3 | 1";

    Pattern pattern = Pattern.compile("([+\\-!(){}\\[\\]^\"~*?:\\\\/]|&&|\\|\\|)");
    Matcher m = pattern.matcher(input);
    String result = m.replaceAll("\\\\$1");

    // Or shorter:

    String result = input.replaceAll("([+\\-!(){}\\[\\]^\"~*?:\\\\/]|&&|\\|\\|)", "\\\\$1");

    // However a Pattern object is re-usable and doesn't incur the overhead 
    // of parsing the regex every time that you use it

    System.out.println("Result: " + result);

I'm afraid that the regex is hard to read because of all the backslash escaping, but it does work.

Output:

Result: blah \&& foo \+ 5 \|| lala & 3 | 1

Note: if you really want to do something wild, which would make it much easier to maintain the list of special characters, then replace the line Pattern pattern = ... with this code, which dynamically builds the regular expression:

    String special = "+ - && || ! ( ) { } [ ] ^ \" ~ * ? : \\ /";
    StringBuilder p = new StringBuilder();
    p.append("(");
    for (String s : special.split("\\s")) {
        if (p.length() > 1)
            p.append('|');
        p.append(Pattern.quote(s));
    }
    p.append(")");

    Pattern pattern = Pattern.compile(p.toString());

Upvotes: 0

Jared
Jared

Reputation: 940

Most of those are single characters, but some ("&&" and "||") are not. The most efficient way (but perhaps not the cleanest solution) would be to simply parse the string and replace characters as needed. The following assumes every special sequence is a single character (so this solution will not work for "&&" or "||":

private static final  StringBuilder sb = new StringBuilder();
// this needs to be synchronized because I'm reusing sb
public synchronized static String replace(final String str){
    // clear out your StringBuilder
    sb.delete(0, sb.length());

    for(final char c : str.toCharArray()){
        if(isSpecial(c))
            sb.append('\\');
        sb.append(c);
    }
    return sb.toString();
}

public static boolean isSpecial(final char c){
    switch(c){
    case '+': 
    case '-': 
    case '!': 
    case '(': 
    case ')': 
    case '{': 
    case '[': 
    case ']':
    case '^':
    case '"':
    case '~':
    case '*':
    case '?':
    case ':':
    case '\\':
    case '/': return true;
    }
    // default (i.e. nothing was recognized) this ins't a special character.
    return false
}

To handle things like "&&" and "||" (I'm assuming you want then to be "\&&" and "\||"--if not, then the above will work fine), then your isSpecial method should take a String a position and test whether this contains the two special characters.

To handle the two double characters, I would do the following (again, perhaps not the most elegant solution--but certainly the most efficient):

private static final StringBuilder sb = new StringBuilder();

// this needs to be synchronized because I'm reusing sb
public synchronized static String replace(final String str){
    // clear out your StringBuilder
    sb.delete(0, sb.length());
    final char[] strArray = str.toCharArray();

    for(int i = 0; i < strArray.length; ++i)
        i = processChar(strArray, i);

    return sb.toString();
}

// this should only be called by the replace method--hence why it is private and not
//    and not public--it requires accessing StringBuilder sb in a synchronized way.
private static boolean processChar(final char[] strArray, final int i){
    final char c = strArray[i];
    switch(c){
    case '+': 
    case '-': 
    case '!': 
    case '(': 
    case ')': 
    case '{': 
    case '[': 
    case ']':
    case '^':
    case '"':
    case '~':
    case '*':
    case '?':
    case ':':
    case '\\':
    case '/': 
        sb.append('\\');
        sb.append(c);
        return i;
    }

    // check for double char sequences:
    if(c == '&'){
        final int nextI = i + 1;
        char nextC;
        if(nextI < strArray.length && (nextC = strArray[nextI]) == '&'){
            sb.append('\\');
            sb.append('&&');
            return nextI;
        }
    }
    // else
    if(c == '|'){
        final int nextI = i + 1;
        char nextC;
        if(nextI < strArray.length && (nextC = strArray[nextI]) == '|'){
            sb.append('\\');
            sb.append('||');
            return nextI;
        }
    }        
    // default (i.e. nothing was recognized) this ins't a special character
    // so just print the character to sb and return i
    sb.append(c);
    return i;
}

Upvotes: 0

npinti
npinti

Reputation: 52185

This would also work:

    String str = "+ - && || ! ( ) { } [ ] ^ \" ~ * ? : \\ /";
    System.out.println(str.replaceAll("(([+!\\(\\)\\{\\}\\[\\]\\^\"~*?:\\/-])|(\\|\\|)|(&&))", "\\\\$1"));

Yields (The extra \ infront of the other \ is escaped when printing):

\+ \- \&& \|| \! \( \) \{ \} \[ \] \^ \" \~ \* \? \: \ \/

Thus given this:

    String str = "(1 + 1) = 2";
    System.out.println(str.replaceAll("(([+!\\(\\)\\{\\}\\[\\]\\^\"~*?:\\/-])|(\\|\\|)|(&&))", "\\\\$1"));

You get this:

    \(1 \+ 1\) = 2

The .replaceAll takes a regular expression as first parameter and a replacement string as the second. If the first argument has regular expression groups, denoted by round brackets, such groups can be accessed in the replacement string through the $ operator followed by the group number. These groups start at 1, with the 0th group being the entire match.

A working example and explanation of the regular expression I provided is available here.

Upvotes: 0

Alexandre Santos
Alexandre Santos

Reputation: 8338

    public static void main(String[] args) throws InterruptedException
    {
        String toBeEscaped = "+-&&||!(){}[]^\"~*?:\\/";
        String input = "(1+1)=2";
        StringBuffer outBuffer = new StringBuffer();
        for (int i = 0; i < input.length(); i++)
        {
            if (toBeEscaped.indexOf((int)input.charAt(i))>-1)
            {
                outBuffer.append("\\");
            }
            outBuffer.append(input.charAt(i));
        }

        System.out.println("Input :"+input);
        System.out.println("Output:"+outBuffer);
    }

Upvotes: 1

shree.pat18
shree.pat18

Reputation: 21757

Try this:

String[] splstrings = {...}; //Your special characters here

String input = "(1+1)=2";

for (String s : splstrings)
{
 input = input.replace(s,"\\"+s);
}

As has been pointed out in the comments, Replace is what you need.

Upvotes: 1

Related Questions