【问题标题】:java escape parenthesisjava转义括号
【发布时间】:2011-06-27 23:11:25
【问题描述】:

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

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

如果我可以改进工作,请发表评论!非常感谢!

【问题讨论】:

  • 您的替换通常是可以的,但是当您的要替换的令牌未修复时,您可能会遇到问题。考虑使用tokens.put(Pattern.quote(original), replacement)。顺便说一句,你不需要组,使用matcher.group(0)
  • 当您使用Pattern.quote 时,您不需要也不能转义括号。所以这是另一种解决方案。
  • 如何使用未编译的正则表达式 (String.matching()) 做到这一点?

标签: java regex escaping parentheses


【解决方案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());

【讨论】:

  • 谢谢,你能举个例子吗:我正在尝试这个:tokens.put(Pattern.quote(":)"), "" );字符串模板 = ":asd: bravo! :)";
  • 但我有一个 NullPointerException
  • 对不起。您必须将原始字符串放入地图中才能找到匹配项。仅在模式中使用带引号的字符串。
  • 这适用于所有解决方案。无论您如何创建匹配字符串的模式,都必须将原始字符串作为键放在 Map 中。
  • 好的,现在如果我使用 Pattern.compile(patternString, Pattern.LITERAL);没有转义,我没有错误,但它没有做替换......非常感谢你的帮助@maartinus! :)
【解决方案2】:

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

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

【讨论】:

  • 这不起作用,它不会编译:“无效的转义序列(有效的是 \b \t \n \f \r \" \' \\ )”
  • @Laphroaig:啊!放两个反斜杠。
  • 使用其中两个! Java源代码中的两个反斜杠意味着String中的一个反斜杠,这是您所需要的。
  • 使用两个反斜杠编译,但不进行替换。
  • 它必须有效。一定有其他问题。忘记它并切换到Pattern.quote,以防您正在寻找精确匹配。
【解决方案3】:

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

假设你有一个字符串词。

word = "http://www.randomwebsite.com/images/That Image (English)";

如果你想用空格替换括号,只需:

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

你必须做 2 个双反斜杠才能让编译器关闭而不是抱怨。

还请记住,该函数返回一个字符串。所以你会这样做

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

除非你想看,直接打印出来。

【讨论】:

    猜你喜欢
    • 2012-02-16
    • 2012-10-28
    • 1970-01-01
    • 2016-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多