Reputation: 10502
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
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
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
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
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
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