i have this little class to make a multiple replace on a string:
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
public class MultipleReplace {
public static void main(String[] args) {
Map<String,String> tokens = new HashMap<String,String>();
tokens.put(":asd:", "<img src=asd.gif>");
tokens.put(":)", "<img src=sorriso.gif>");
String template = ":asd: bravo! :)";
String patternString = "(" + StringUtils.join(tokens.keySet(), "|") + ")";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(template);
StringBuffer sb = new StringBuffer();
while(matcher.find()) {
matcher.appendReplacement(sb, tokens.get(matcher.group(1)));
}
matcher.appendTail(sb);
System.out.println(sb.toString());
}
}
The problem is 开发者_运维问答on the second replace, where i have a parenthesis that result in:
Exception in thread "main" java.util.regex.PatternSyntaxException: Unmatched closing ')' near index 8 (:)|:asd:)
How i can escape the parenthesis? Or, can you suggest an alternative to do this multiple replace?
Thank you very much and sorry for my english :)
EDIT:
Escaping with backslash ')' doesn't work too, it won't compile:
"Invalid escape sequence (valid ones are \b \t \n \f \r \" \' \ )"
NEW EDIT
using two backslashes compile, but doesn't do the replacement.
LAST EDIT
Finally found the solution, using Pattern.quote while building the pattern. Have to use an iterator to do the loop.
Here the correct code:
package string;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MultipleReplace {
@SuppressWarnings("rawtypes")
public static void main(String[] args) {
Map<String,String> tokens = new HashMap<String,String>();
tokens.put(":asd:", "<img src=asd.gif>");
tokens.put(":)", "<img src=sorriso.gif>");
String template = ":asd: bravo! :)";
Iterator it = tokens.entrySet().iterator();
String patternString = "(";
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
patternString = patternString +Pattern.quote((String) pairs.getKey());
if (it.hasNext())
{
patternString = patternString + "|";
}
}
patternString = patternString + ")";
System.out.println(patternString);
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(template);
StringBuffer sb = new StringBuffer();
while(matcher.find()) {
matcher.appendReplacement(sb, tokens.get(matcher.group(1)));
}
matcher.appendTail(sb);
System.out.println(sb.toString());
}
}
Please comment on it if i can improve the work! Thank you very much!
Use Pattern.quote
like I wrote in the comment. It works with every string and for long Strings containing a lot of non alphanumerical chars it's less error-prone.
Update
This is a shiny (and untested) Java 8 solution:
final Map<String, String> tokens = new HashMap<>();
tokens.put(":asd:", "<img src=asd.gif>");
tokens.put(":)", "<img src=sorriso.gif>");
final String template = ":asd: bravo! :)";
final String patternString = tokens.keySet()
.stream().map(Pattern::quote).collect(Collectors.joining("|"));
final Pattern pattern = Pattern.compile(patternString);
final Matcher matcher = pattern.matcher(template);
final StringBuffer sb = new StringBuffer();
while (matcher.find()) {
matcher.appendReplacement(sb, tokens.get(matcher.group(0)));
}
matcher.appendTail(sb);
System.out.println(sb.toString());
Use a backslash: \)
. Parens must be escaped because they can be used to group parts of the regex.
String template = ":asd: bravo\\! :\\)";
I'll give a better example than Tim N.
Let's say you have a String word.
word = "http://www.randomwebsite.com/images/That Image (English)";
If you want to replace brackets with spaces, simply do:
word.replaceAll("\\(", " ");
You have to do 2 double back slashes to get the compiler to shut up and not whine.
Also keep in mind, that function returns a String. So you'd do
word = word.replaceAll("\\(", " ");
Unless you want to see it, just print it out.
精彩评论