String.replaceВсе одиночная обратная косая черта с двойной обратной косой чертой
Я пытаюсь преобразовать String
\something\
в String
\\something\\
using replaceAll
, но я все время получаю всевозможные ошибки. Я думал, что это решение:
theString.replaceAll("\\", "\\\\");
Но это дает следующее исключение:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
- Договор сравнения и компаратора относительно нулевого
- Строки, записанные в файл, не сохраняют разрывы строк
- Как отправить и получить сериализованный объект в канале сокета
- NoClassDefFoundError на зависимость от Maven
- В Java собрано мусор пространства постоянного поколения?
- java.io.StreamCorruptedException: недопустимый код типа: 00
- Как получить высоту и ширину изображения с помощью java?
- JavaFX запускает другое приложение
- Аутентификация Active Directory с помощью Java на Linux
- Что эквивалентно classу Java BigDecimal в C #?
- Как использовать invokeAll (), чтобы все пулы streamов выполняли свою задачу?
- Доступ к элементам элементов в JSONArray с помощью Java
- Как клон работает под капотом?
String#replaceAll()
интерпретирует аргумент как регулярное выражение . Параметр \
является escape-символом как в String
и в regex
. Вам нужно дважды уйти от него для регулярного выражения:
string.replaceAll("\\\\", "\\\\\\\\");
Но для этого вам не обязательно нужно регулярное выражение, просто потому, что вам нужна точная замена по-символу, и вам здесь не нужны шаблоны. Поэтому String#replace()
должно быть достаточным:
string.replace("\\", "\\\\");
Обновление : согласно комментариям, вы, похоже, хотите использовать строку в контексте JavaScript. Возможно, вам лучше использовать StringEscapeUtils#escapeEcmaScript()
чтобы покрыть больше символов.
Чтобы избежать replaceAll
проблем, вы можете использовать replace
(который принимает простую строку) вместо replaceAll
(который принимает регулярное выражение). Вам все равно придется скрывать обратную косую черту, но не в диких направлениях, требуемых регулярными выражениями.
Вам нужно будет избежать обратного слэша (escaped) в первом аргументе, поскольку это регулярное выражение. Замена (второй аргумент – см. Matcher # replaceAll (String) ) также имеет особое значение обратных косых черт, поэтому вам придется заменить их на:
theString.replaceAll("\\\\", "\\\\\\\\");
replaceAll(target, replacement)
использует синтаксис регулярного выражения (regex) для target
и частично для replacement
.
Проблема заключается в том, что \
является специальным символом в регулярном выражении (например, \d
для представления цифры) и в литерале строки (например, \n
для создания разделителя строк или \"
для представления символа двойной кавычки), и для создания символа \
нам нужно убежать с ним дополнительно \
перед этим на обоих этих уровнях.
Таким образом, чтобы создать target
регулярное выражение, которое будет представлять символ \
нам нужно сбежать дважды:
- в регулярном выражении
\\
- Строковый литерал
"\\\\"
(каждый\
нуждается в его дополнительном\
перед).
В случае replacement
\
также является специальным, чтобы избежать другого специального символа, который равен $
. Через нотацию $x
часть данных, сопоставляемая регулярным выражением, может быть доступна и повторно использована взамен, например replaceAll("(\d)", "$1$1")
будет дублировать каждую цифру.
Итак, опять же, чтобы иметь единственный \
в replacement
нам нужен текст, представляющий две обратные косые черты:
-
\\
- но строковый литерал, представляющий
\\
выглядит как"\\\\"
НО, так как мы хотим поставить два \
в замене, нам нужно "\\\\\\\\"
там (два "\\\\"
).
replaceAll("\\\\", "\\\\\\\\");
Чтобы упростить жизнь, Java предоставляет инструменты для автоматического удаления текста в target
и replacement
части. Итак, теперь мы можем сосредоточиться только на строках и забыть о синтаксисе regex:
replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement))
который в нашем случае может выглядеть
replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\"))
Или даже проще, если мы не хотим использовать regex, мы не replaceAll
включать replaceAll
и вместо этого replaceAll
использовать replace
(оба метода заменят все target
s, но во втором не будет синтаксис regex). Так что вы могли бы просто написать
theString = theString.replace("\\", "\\\\")
Да … к тому времени, когда компилятор регулярных выражений увидит шаблон, который вы ему дали, он видит только одну обратную косую черту (поскольку лексер Java превратил двойной backwhack в один). Вам нужно заменить "\\\\"
на "\\\\"
, верьте или нет! Java действительно нуждается в хорошем синтаксисе строки.