Я пытаюсь преобразовать String
\something\
в String
\\something\\
using replaceAll
, но продолжаю получать всевозможные ошибки. Я думал, что это решение:
theString.replaceAll("\\", "\\\\");
Но это дает следующее исключение:
java.util.regex.PatternSyntaxException: Unexpected internal error near index 1
источник
String#replaceAll()
все равно хотите использовать , вы можете указать строку замены с помощью Matcher # quoteReplacement () :theString.replaceAll("\\", Matcher.quoteReplacement("\\\\"));
Чтобы избежать такого рода проблем, вы можете использовать
replace
(который принимает простую строку) вместоreplaceAll
(который принимает регулярное выражение). Вам все равно нужно будет избегать обратной косой черты, но не так, как это требуется для регулярных выражений.источник
TL; DR: используйте
theString = theString.replace("\\", "\\\\");
вместо этого.проблема
replaceAll(target, replacement)
использует синтаксис регулярного выражения (regex) дляtarget
и частично дляreplacement
.Проблема в том, что
\
это специальный символ в регулярном выражении (его можно использовать как\d
цифру) и в строковом литерале (его можно использовать, например,"\n"
для представления разделителя строк или\"
для экранирования символа двойной кавычки, который обычно представляет конец строкового литерала).В обоих этих случаях для создания
\
символа мы можем избежать его (сделать его буквальным вместо специального символа), поместив\
перед ним дополнительный (как мы экранируем"
строковые литералы через\"
).Таким образом , чтобы
target
регулярное выражение , представляющий\
символ будет нужно держать\\
, и строку символов , представляющими такой текст нужно будет выглядеть"\\\\"
.Так мы
\
дважды сбежали :\\
"\\\\"
(каждый\
представлен как"\\"
).В случае там
replacement
\
тоже особенное. Это позволяет нам избежать другого специального символа,$
который через$x
нотацию позволяет нам использовать часть данных, сопоставленных регулярным выражением и удерживаемых путем захвата группы, индексированной какx
, например,"012".replaceAll("(\\d)", "$1$1")
будет соответствовать каждой цифре, поместить ее в группу захвата 1 и$1$1
заменить ее двумя своими копиями (он будет дублировать его) в результате"001122"
.Итак, снова, чтобы
replacement
представить\
литерал, нам нужно избежать его с помощью additional,\
что означает, что:\\
\\
как выглядит"\\\\"
НО, поскольку мы хотим
replacement
сохранить две обратные косые черты, нам понадобятся"\\\\\\\\"
(каждая\
представлена одной"\\\\"
).Таким образом, версия с
replaceAll
может выглядеть какБолее простой способ
Для того, чтобы сделать жизнь проще из Java предоставляет инструменты для автоматического ускользают текст в
target
иreplacement
частях. Итак, теперь мы можем сосредоточиться только на строках и забыть о синтаксисе регулярных выражений:что в нашем случае может выглядеть как
Даже лучше
Если нам действительно не нужна поддержка синтаксиса регулярных выражений, давайте вообще не будем задействовать
replaceAll
. Вместо этого давайте использоватьreplace
. Оба метода заменят всеtarget
s, ноreplace
не используют синтаксис регулярных выражений. Чтобы вы могли просто написатьисточник
Вам нужно будет экранировать (экранированную) обратную косую черту в первом аргументе, поскольку это регулярное выражение. Замена (2-й аргумент - см. Matcher # replaceAll (String) ) также имеет особое значение обратной косой черты, поэтому вам придется заменить их на:
источник
Да ... к тому времени, когда компилятор регулярных выражений увидит заданный вами шаблон, он увидит только одну обратную косую черту (поскольку лексер Java превратил двойной обратный удар в одиночный). Вам нужно заменить
"\\\\"
на"\\\\"
, хотите верьте, хотите нет! Java действительно нужен хороший синтаксис необработанных строк.источник