文字列の置換

文字列の置換にはString#replaceAllを使うことが多い。
# 別にPatternとか使ってもいいけど、めんどいので。
でも、なんだかうまくいかないことがあった。


円マーク1つを2つに置換する、という処理を実装しようとした。
この場合、replaceAllに渡す引数は、次のようになる(と思ってた)。

  • 正規表現:"\\\\" → 正規表現のエンジンに円マーク2つが渡されるので、円マーク1つとマッチする。
  • 置換文字:"\\\\" → 置き換える文字なので、Stringレベルでの指定(のはず)。


コードだと、こんな感じ。


String target = "\\";

String regex = "\\\\";
String replace = "\\\\";

String result = target.replaceAll(regex, replace);


でも、これは間違いコードで、置換文字には"\\\\\\\\"を指定しないとうまくいかない。
これが、どーにもこーにも納得できないっす。


とりあえず、うまくいくコード。


public static void main(String[] args) {
// 円マーク1つ
String target = "\\";

String regex = "\\\\";
String replace = "\\\\\\\\";

String result = target.replaceAll(regex, replace);

System.out.println("result: " + result);
System.out.println("replace: " + replace);
}


実行結果。


result: \\
replace: \\\\


これって、つまりは置換したい文字に置換できてない(円マーク4つを指定したのに、2つになった)
気がするんだけど、なんでだろー。
円マーク1つに置換したい場合は、"\\\\"を指定するってこと?






と、ここまで書いた後、1.5のJavadocを見たら、Matcher#replaceAllに答えがありました。

置換文字列内で円マーク (\) とドル記号 ($) を使用すると、それをリテラル置換文字列として処理した場合とは結果が異なる場合があります。ドル記号は、先に説明したとおり、先方参照された部分シーケンスへの参照として処理される場合があり、円マークは置換文字列内のリテラル文字をエスケープするのに使用されます。

1.4のJavadocには上記の記述がないんだけど、そりぁー不親切すぎじゃないっすか?
はぁ。




正規表現を使うと、可読性が少しはいいかなーと思ってたんだけど、
円マークが8個も続いたら、コメント書かないと何やってんのかわからんなぁ。