String
を使用してString
\something\
をreplaceAll
\\something\\
に変換しようとしていますが、あらゆる種類のエラーが発生し続けます。私はこれが解決策だと思った:
theString.replaceAll("\\", "\\\\");
ただし、これには以下の例外があります。
Java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
String#replaceAll()
は、引数を 正規表現 として解釈します。 \
は、bothString
およびregex
のエスケープ文字です。あなたは正規表現のためにそれを二重エスケープする必要があります:
string.replaceAll("\\\\", "\\\\\\\\");
ただし、正確な文字ごとの置換が必要であり、ここでパターンが必要ないという理由だけで、必ずしも正規表現は必要ありません。 String#replace()
で十分です:
string.replace("\\", "\\\\");
Update:コメントによると、JavaScriptコンテキストで文字列を使用したいようです。代わりに StringEscapeUtils#escapeEcmaScript()
を使用して、より多くの文字をカバーする方がよいでしょう。
この種の問題を回避するには、replace
(正規表現を使用)の代わりにreplaceAll
(プレーン文字列を使用)を使用できます。それでもバックスラッシュをエスケープする必要がありますが、正規表現で必要なワイルドな方法ではありません。
TLDR:代わりにtheString = theString.replace("\\", "\\\\");
を使用します。
replaceAll(target, replacement)
は、target
に正規表現(regex)構文を使用し、replacement
に部分的に使用します。
問題は、\
が正規表現(数字を表す\d
のように使用できる)および文字列リテラル(行区切りを表す"\n"
のような特殊文字であるか、または通常文字列リテラルの終わりを表す二重引用符をエスケープする\"
であるということです)。
これらの両方の場合で\
シンボルを作成するには、追加する\
を前に追加することにより(特殊文字の代わりにリテラルにする)escapeできます("
を介して文字列リテラルで\"
をエスケープするように) 。
\
シンボルを表すtarget
正規表現は\\
を保持する必要があり、そのようなテキストを表す文字列リテラルは"\\\\"
のように見える必要があります。
そこで、\
を2回エスケープしました。
\\
"\\\\"
に1回(各\
は"\\"
として表されます)。replacement
の場合、\
も特別です。他の特殊文字$
をエスケープして、$x
表記を使用して、正規表現に一致し、"012".replaceAll("(\\d)", "$1$1")
が各桁に一致するなど、x
としてインデックス付けされたグループをキャプチャすることで保持されるデータの一部を使用できるようにしますグループ1をキャプチャすると、$1$1
は2つのコピーに置き換えられ(複製されます)、"001122"
になります。
繰り返しますが、replacement
が\
リテラルを表すようにするには、追加の\
でエスケープする必要があります。
\\
を含める必要があります\\
を表す文字列リテラルは"\\\\"
のように見えますただし、replacement
にtwoバックスラッシュを保持する必要があるため、"\\\\\\\\"
(1つの\
で表される各"\\\\"
)が必要になります。
したがって、replaceAll
を含むバージョンは次のようになります。
replaceAll("\\\\", "\\\\\\\\");
生活を楽にするために、Javaは、テキストをtarget
およびreplacement
部分に自動的にエスケープするツールを提供します。そのため、文字列のみに注目し、正規表現の構文を忘れることができます。
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
この場合、次のようになります
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
正規表現の構文サポートが本当に必要ない場合は、replaceAll
をまったく含めないでください。代わりにreplace
を使用してください。両方のメソッドがalltarget
sを置き換えますが、replace
は正規表現構文を含みません。だからあなたは単に書くことができます
theString = theString.replace("\\", "\\\\");
正規表現であるため、最初の引数の(エスケープされた)バックスラッシュをエスケープする必要があります。置換(2番目の引数- Matcher#replaceAll(String) を参照)にはバックスラッシュの特別な意味もあるため、これらを次のように置換する必要があります。
theString.replaceAll("\\\\", "\\\\\\\\");
はい...正規表現コンパイラが指定されたパターンを見るまでに、バックスラッシュは1つだけ表示されます(Javaのレクサーがダブルバックワックを1つに変えたため)。 "\\\\"
を"\\\\"
に置き換える必要があります。信じられないかもしれません! Javaには、適切な生の文字列構文が本当に必要です。