В дополнение к уже выбранному ответу (и различным информационным сообщениям здесь) я настоятельно рекомендую захватить копию Head First Design Patterns . Это очень простое чтение и ответит на ваш вопрос напрямую, объясните, почему это важно, и покажите вам много шаблонов программирования, которые вы можете использовать, чтобы использовать этот принцип (и другие).
String#replaceAll()
интерпретирует этот аргумент как регулярное выражение . \
является escape-символом как в String
, так и в regex
. Вам нужно дважды уйти от него для регулярного выражения:
string.replaceAll("\\\\", "\\\\\\\\");
Но для этого вам не обязательно нужно регулярное выражение, просто потому, что вам нужна точная замена по каждому символу, и вам не нужны шаблоны Вот. Поэтому String#replace()
должно быть достаточно:
string.replace("\\", "\\\\");
Обновление: согласно комментариям, вы, похоже, хотите использовать строку в контексте JavaScript. Возможно, вам лучше использовать StringEscapeUtils#escapeEcmaScript()
, чтобы покрыть больше символов.
Чтобы избежать подобных проблем, вы можете использовать replace
(который принимает простую строку) вместо replaceAll
(который принимает регулярное выражение). Вам все равно придется скрывать обратную косую черту, но не в диких направлениях, требуемых с помощью регулярных выражений.
Да ... к тому времени, когда компилятор regex увидит шаблон, который вы ему дали, он видит только одну обратную косую черту (поскольку лексер Java превратил двойной backwhack в один). Вы должны заменить "\\\\"
на "\\\\"
, верьте или нет! Java действительно нуждается в хорошем синтаксисе строки.
replaceAll(target, replacement)
использует синтаксис регулярного выражения (regex) для target
и частично для replacement
.
Проблема в том, что \
является специальным символом в регулярном выражении (например, \d
представляет цифру) и в литерале строки (например \n
для создания разделителя строк или \"
для представления символа двойной кавычки) , и для создания символа \
нам нужно убрать его с дополнительным \
перед ним на обоих этих уровнях.
Итак, чтобы создать target
регулярное выражение, которое будет представлять символ \
, нам нужно сбежать это дважды:
\\
"\\\\"
(перед каждым \
требуется еще один \
). В случае replacement
\
также является специальным для выхода из другого специального символа, который является $
. Через нотацию $x
часть данных, сопоставляемых регулярным выражением, может быть доступна и повторно использована при замене, например replaceAll("(\d)", "$1$1")
будет дублировать каждую цифру.
Итак, чтобы иметь single \
в replacement
, нам нужен текст, представляющий две обратные косые черты:
\\
\\
, выглядит как "\\\\"
, но поскольку мы хотим заменить на два \
, нам нужно "\\\\\\\\"
там (два "\\\\"
).
replaceAll("\\\\", "\\\\\\\\");
Чтобы облегчить жизнь, Java предоставляет инструменты для автоматического выхода текста в target
и replacement
части. Итак, теперь мы можем сосредоточиться только на строках и забыть о синтаксисе regex:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
, который в нашем случае может выглядеть как
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
Или даже проще, если мы не хотите использовать regex, не включает replaceAll
, а вместо этого позволяет использовать replace
(оба метода заменят все target
s, но во втором не будет синтаксис regex). Поэтому вы можете просто написать
theString = theString.replace("\\", "\\\\")
Вам нужно будет избежать обратного слэша (экранированного) в первом аргументе, поскольку это регулярное выражение. Замена (второй аргумент - см. Matcher # replaceAll (String) ) также имеет особое значение обратных косых черт, поэтому вам придется заменить их на:
theString.replaceAll("\\\\", "\\\\\\\\");
String#replaceAll()
, вы можете процитировать заменяющую строку с помощью Matcher # quoteReplacement () :theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
– ph.dev 12 November 2015 в 18:06