java转义括号

java转义括号,java,regex,escaping,parentheses,Java,Regex,Escaping,Parentheses,我有一个小类来对字符串进行多次替换: 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) {

我有一个小类来对字符串进行多次替换:

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());
    }
}
import java.util.HashMap;
导入java.util.Map;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
导入org.apache.commons.lang.StringUtils;
公共类多路复用{
公共静态void main(字符串[]args){
Map tokens=newhashmap();
代币。放置(“:asd:”,“);
代币。放置(“:)”,“);
字符串模板=“:asd:bravo!:)”;
String patternString=“(“+StringUtils.join(tokens.keySet(),“|”)+”);
Pattern=Pattern.compile(patternString);
Matcher Matcher=pattern.Matcher(模板);
StringBuffer sb=新的StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb,tokens.get)(matcher.group(1));
}
(某人);
System.out.println(sb.toString());
}
}
问题出现在第二次替换中,其中有一个括号导致:

索引8附近的线程“main”java.util.regex.PatternSyntaxException:Unmatched closing')中出现异常 (:)|:asd:)

我怎样才能避开括号? 或者,您可以建议一种替代方法来进行多次替换吗

非常感谢,对不起,我的英语:)

编辑:

使用反斜杠“)”进行转义也不起作用,它无法编译:

“无效的转义序列(有效的是\b\t\n\f\r\”\”)”

新编辑


使用两个反斜杠编译,但不进行替换

上次编辑

最终找到了解决方案,在构建模式时使用Pattern.quote。必须使用迭代器进行循环

下面是正确的代码:

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());
    }
}
包字符串;
导入java.util.HashMap;
导入java.util.Iterator;
导入java.util.Map;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
公共类多路复用{
@抑制警告(“原始类型”)
公共静态void main(字符串[]args){
Map tokens=newhashmap();
代币。放置(“:asd:”,“);
代币。放置(“:)”,“);
字符串模板=“:asd:bravo!:)”;
迭代器it=tokens.entrySet().Iterator();
字符串模式字符串=“(”;
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.compile(patternString);
Matcher Matcher=pattern.Matcher(模板);
StringBuffer sb=新的StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb,tokens.get)(matcher.group(1));
}
(某人);
System.out.println(sb.toString());
}
}
如果我能改进工作,请发表评论!非常感谢!

使用反斜杠:
\)
。必须转义参数,因为它们可以用于对正则表达式的部分进行分组

    String template = ":asd: bravo\\! :\\)";

使用
Pattern.quote
,就像我在评论中写的那样。它适用于每个字符串,对于包含大量非字母数字字符的长字符串,它不太容易出错

更新 这是一个闪亮的(未经测试的)Java 8解决方案:

    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());
final Map tokens=new HashMap();
代币。放置(“:asd:”,“);
代币。放置(“:)”,“);
最终字符串模板=“:asd:bravo!:)";
final String patternString=tokens.keySet()
.stream().map(Pattern::quote).collect(收集器.joining(“|”);
最终模式=Pattern.compile(模式字符串);
最终匹配器匹配器=pattern.Matcher(模板);
最终StringBuffer sb=新StringBuffer();
while(matcher.find()){
matcher.appendReplacement(sb,tokens.get)(matcher.group(0));
}
(某人);
System.out.println(sb.toString());

我举一个比Tim N更好的例子

假设你有一个字符串

word = "http://www.randomwebsite.com/images/That Image (English)";
如果要用空格替换方括号,只需执行以下操作:

word.replaceAll("\\(", " ");
你必须做2个双反斜杠才能让编译器闭嘴而不发牢骚

请记住,该函数返回一个字符串

word = word.replaceAll("\\(", " ");

除非你想看,否则就把它打印出来。

这行不通,它不会编译:“无效的转义序列(有效的是\b\t\n\f\r\”\'\\)”@Laphroaig:Ah!放两个反斜杠,用两个!Java源代码中的两个反斜杠意味着字符串中的一个反斜杠,这是您所需要的。使用两个反斜杠编译,但不进行替换。它必须工作。一定是出了什么事。忘记它并切换到
模式。如果您正在寻找精确匹配,请引用
。您的替换通常是可以的,但如果您的待替换令牌未修复,您可能会遇到问题。考虑使用<代码>令牌。放置(模式。引用(原始),替换)< /代码>。顺便说一句,你不需要分组,使用
matcher.group(0)
。当你使用
Pattern.quote时,你不需要也不可以逃出参数。这是另一个解决方案。我如何使用未编译的正则表达式(String.matching())来实现这一点?谢谢,您能提供一个示例:我正在尝试:tokens.put(Pattern.quote(“:”)”);字符串模板=“:asd:bravo!:)”;但是我有一个空点异常,很抱歉。必须将原始字符串放入映射中才能找到匹配项。仅在模式中使用带引号的字符串。这适用于所有解决方案。无论您如何创建模式来逐字匹配字符串,都必须将原始字符串作为键放入映射中。好的,现在如果我使用pattern.compile(patternString,pattern.LITERAL);没有转义,我没有错误,但它不做替换。。。非常感谢你