JavaのString#replaceAllによる正規表現置換でも、$1などでグループ化した文字列を後方参照できる

タイトル通りだが、チーム内の誰もできるということを知らなかったのでメモ。

replaceAllでの後方参照

タイトル通り、第1引数の検索文字列に () で囲んだグループを記述し、第2引数の置換文字列に ${n}$n を記述すると、検索文字内のグループ化した文字列を後方参照できる。

また、 String#replaceFirst でも同様に置換可能。

assert "abc".replaceAll("(^.)", "$1$1").equals("aabc");
assert "abc".replaceFirst("(^.)", "$1$1").equals("aabc");

Groovyの場合

Groovyでは、ダブルクォーテーションによる文字列リテラルを使用すると、$ がGStringの変数展開とみなされる。

シングルクォーテーションまたはスラッシュで囲むか、ダブルクォーテーション内では $ をバックスラッシュでエスケープする必要がある。

assert "abc".replaceAll("(^.)", /$1$1/) == "aabc"
assert "abc".replaceFirst("(^.)", "\$1\$1") == "aabc"

Kotlinの場合

KotlinのString#replace()でもGroovyと同様に、第2引数の $エスケープなど必要かと思ったが、不要だった。

変数名として数値が使えないため、そのあたり判定してくれているのかもしれない。

assert("abc".replace("(^.)".toRegex(), "$1$1") == "aabc")

振り返り

なんでできること知らなかったの? と聞くと、

unageanu.hatenablog.com

のように、「Javaでできると思わなかった」という答えが返ってきた。

上記リンクや下記リンクのように、定期的に記事になっている気がする。

kazuhira-r.hatenablog.com