29

私は最近、 String.replaceAll(regex,replacement) がエスケープ文字「\」(スラッシュ)に関して非常に奇妙な動作をすることに気付きました

たとえば、filepath -String text = "E:\\dummypath" を含む文字列があり、これを に置き換えたいと"\\""/"ます。

text.replace("\\","/")出力を与えますが、"E:/dummypath"例外を発生さtext.replaceAll("\\","/")せますjava.util.regex.PatternSyntaxException

で同じ機能を実装したい場合は、次のreplaceAll()ように記述する必要があります。 text.replaceAll("\\\\","/")

注目すべき違いの 1 つは、引数が文字列であるのreplaceAll()に対して、引数が正規表現であることです。replace()

ただしtext.replaceAll("\n","/")、同等の文字シーケンスとまったく同じように機能しますtext.replace("\n","/")

さらに掘り下げる: 他の入力を試すと、さらに奇妙な動作が観察されることがあります。

割り当てましょうtext="Hello\nWorld\n"

さて、 text.replaceAll("\n","/")text.replaceAll("\\n","/")text.replaceAll("\\\n","/")これら3つすべてが同じ出力を与えますHello/World/

Java は、私が感じる最善の方法で正規表現をめちゃくちゃにしてしまったのです! 正規表現でこれらの遊び心のある動作を行う言語は他にないようです。Javaがこのように台無しになった特定の理由はありますか?

4

6 に答える 6

28

Java 用に 1 回、正規表現用に 1 回、2 回 esacpe する必要があります。

Javaコードは

"\\\\"

の正規表現文字列を作成します

"\\" - two chars

しかし、正規表現にもエスケープが必要なので、次のようになります

\ - one symbol
于 2013-09-18T15:06:34.607 に答える
-2

この問題を回避する 1 つの方法は、バックスラッシュを別の文字に置き換え、その代用文字を中間置換に使用してから、最後にバックスラッシュに戻すことです。たとえば、「\r\n」を「\n」に変換するには:

String out = in.replace('\\','@').replaceAll("@r@n","@n").replace('@','\\');

もちろん、入力文字列に出現する可能性のある置換文字を選択すると、うまく機能しません。

于 2015-07-29T18:12:49.283 に答える
-2

これは、Java が置換文字列に特別な意味を与えようとする\ため、\$ はリテラルの $ 記号になりますが、その過程で実際の特別な意味を削除したように見えます。\

,text.replaceAll("\\\\","/")は少なくともある意味では問題ないと考えられますが (それ自体は完全に正しいわけではありません)、同じ出力を与える , の 3 つの実行はすべてさらにtext.replaceAll("\n","/")おかしなことに思えます。同じ理由での機能を制限した理由については、矛盾しています。text.replaceAll("\\n","/")text.replaceAll("\\\n","/")text.replaceAll("\\","/")

Java は正規表現を台無しにしませんでした。それは、Java が、まったく必要のないときに、何かユニークで異なることをしようとして、コーダーを台無しにするのが好きだからです。

于 2013-09-18T17:09:46.523 に答える