CLOVER🍀

That was when it all began.

Matcher#replaceAll、String#replaceAllで後方参照が使える

コロッと忘れていたようなので、メモ。

java.util.regex.Matcher#replaceAllやreplaceFirst、String#replaceAllやreplaceFirstで$を使った後方参照が使えます。

普段あんまりJava正規表現による置換を多用しないのと、Perlに頼り切ってることが多かったですからねぇ。あとはMatcher#groupを使ってたような…。

こんな感じで、まずはjava.util.regexパッケージを使用する場合。

        String target = "Hello 1234 World 5678";

        Pattern p = Pattern.compile("[^\\d]+ (\\d+) [^\\d]+ (\\d+)");
        Matcher m = p.matcher(target);

        System.out.println(m.replaceAll("Numbers = [$1 $2], origin = [$0]"));
        // => Numbers = [1234 5678], origin = [Hello 1234 World 5678]

$1、$2…と後方参照が可能です。$0を指定した場合は、マッチした文字列全体が取れます。

Stringクラスだけでも大丈夫。

        System.out.println(target.replaceAll("[^\\d]+ (\\d+) [^\\d]+ (\\d+)", "Numbers = [$1 $2], origin = [$0]"));
        // => Numbers = [1234 5678], origin = [Hello 1234 World 5678]

Javaでいけるなら、GroovyでもOK。

def target = 'Hello 1234 World 5678'
println(target.replaceAll(/[^\d]+ (\d+) [^\d]+ (\d+)/, 'Numbers = [$1 $2], origin = [$0]'))
// => Numbers = [1234 5678], origin = [Hello 1234 World 5678]

def p = ~/[^\d]+ (\d+) [^\d]+ (\d+)/
def m = (target =~ p)
println(m.replaceAll('Numbers = [$1 $2], origin = [$0]'))
// => Numbers = [1234 5678], origin = [Hello 1234 World 5678]

Groovyの場合は、GStringと混ざらないようにシングルクォートで囲むべしって感じですか。

Scalascala.util.matching.Regexでもいけます。

val target = "Hello 1234 World 5678"
val regex = """[^\d]+ (\d+) [^\d]+ (\d+)""".r
println(regex.replaceAllIn(target, "Numbers = [$1 $2], origin = [$0]"))
// => Numbers = [1234 5678], origin = [Hello 1234 World 5678]

たまには使ってみましょうっと。