【Java】ダブルクォートを replace()と replaceAll()で置換しようとしたときの違い

初歩的な知識不足、見逃しのような気もするけどメモしとく。

二重エスケープを避けるため、既にエスケープされているダブルクォートはそのままで、エスケープされていないダブルクォートだけ置換したかったのでString.replaceAll()で正規表現(否定先読み)を使って置換しようとしたが、ダブルクォートがヒットしてくれず上手くいかない。環境はJava8

str.replaceAll("(?<!\)\"", "\"");

ちなみに、ブラウザ上で正規表現をチェックできるサイトでやってみるとしっかりヒットする。

regex-testdrive.com

いろいろとこねくり回していると、replaceAll()でダブルクォートは「"」ではなく「\"」としなければならないぽい。ちなみに同じ置換を行うメソッドreplace()だと「"」で上手くいく。

両者の違いは引数に正規表現をとるかどうか、くらいの認識しかないのだけど、なぜreplaceAll()だと「\"」になるのか分からない。

// replaceAll()の場合
str.replaceAll("\"", "\\\"");

// replace()の場合
str.replace(""", "\"");