java 转义括号

2022-09-03 12:45:59

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

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());
    }
}

问题在第二个替换上,其中我有一个括号,导致:

线程“main” java.util.regex.PatternSyntaxException: 在索引 8 附近不匹配的结束 ')' 中的异常 (:)|: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());
    }
}

如果我能改进工作,请评论它!谢谢!


答案 1

使用我在评论中写的内容。它适用于每个字符串,对于包含大量非字母数字字符的长字符串,它不容易出错。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());

答案 2

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

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