14

文字列を複数置換するためのこの小さなクラスがあります。

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

問題は2番目の置換にあります。ここでは、括弧が次のようになります。

スレッド「メイン」での例外 java.util.regex.PatternSyntaxException: インデックス 8 付近で一致しない終了 ')' (:)|:asd:)

どうすれば括弧をエスケープできますか? または、この複数の置換を行う代替案を提案できますか?

どうもありがとうございました。私の英語で申し訳ありません:)

編集:

バックスラッシュ ')' でのエスケープも機能せず、コンパイルされません:

「無効なエスケープ シーケンス (有効なものは \b \t \n \f \r \" \' \ )"

新しい編集

2 つのバックスラッシュを使用するとコンパイルされますが、置換は行われません。

最終編集

最後に、パターンの構築中に 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());
    }
}

仕事を改善できる場合は、コメントしてください!どうもありがとうございました!

4

3 に答える 3

16

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());
于 2011-02-15T22:33:55.863 に答える
8

バックスラッシュを使用します: \). 括弧は、正規表現の一部をグループ化するために使用できるため、エスケープする必要があります。

    String template = ":asd: bravo\\! :\\)";
于 2011-02-15T22:19:57.530 に答える
1

Tim Nよりも良い例を挙げましょう。

文字列の単語があるとしましょう。

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

括弧をスペースに置き換えたい場合は、次のようにします。

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

コンパイラーをシャットダウンさせ、泣き言を言わないようにするには、2 つの二重バック スラッシュを実行する必要があります。

また、その関数は文字列を返すことに注意してください。だからあなたはするだろう

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

見たくない場合は、印刷してください。

于 2012-12-16T05:28:38.443 に答える