2009-11-09 4 views
90

Я пытаюсь преобразовать String\something\ в String\\something\\ используя replaceAll, но я получаю все виды ошибок. Я думал, что это было решение:String.replaceAll одиночные обратные косые с двойной обратной косой черты

theString.replaceAll("\\", "\\\\"); 

Но это дает ниже исключение:

java.util.regex.PatternSyntaxException: Unexpected internal error near index 1 

ответ

162

String#replaceAll() интерпретирует аргумент как regular expression. \ является символом пробега в иString и regex. Вы должны дважды денешься для регулярных выражений:

string.replaceAll("\\\\", "\\\\\\\\"); 

Но вам не обязательно нужно регулярное выражение для этого, просто потому, что вы хотите, точный характер, по-символ замены и вам не нужны шаблоны здесь. Так String#replace() должно хватить:

string.replace("\\", "\\\\"); 

Update: согласно комментариям, вы, кажется, хотите использовать строку в контексте JavaScript. Возможно, вам лучше использовать StringEscapeUtils#escapeEcmaScript() вместо этого, чтобы накрыть больше символов.

+0

Фактически, он используется в JavaScript AST, который должен быть преобразован обратно в исходный код. Ваше решение работает. Благодаря! –

+0

Если вы хотите использовать 'String # replaceAll()' в любом случае, вы можете привести строку замены с помощью [Matcher # quoteReplacement()] (http://docs.oracle.com/javase/7/docs/api/java/ util/regex/Matcher.html # quoteReplacement (java.lang.String)): 'theString.replaceAll (" \\ ", Matcher.quoteReplacement (" \\\\ "));' –

6

Вы должны будете бежать (бежал) обратной косой черты в первом аргументе, как это регулярное выражение. Замена (второй аргумент - см Matcher#replaceAll(String)) также имеет свой особый смысл обратной косой черты, так что вам придется заменить тех:

theString.replaceAll("\\\\", "\\\\\\\\"); 
3

Да ... к тому времени, регулярное выражение компилятор видит образец, который Вы дали он видит только одну обратную косую черту (поскольку лексер Java превратил двойной backwhack в один). Вам нужно заменить "\\\\" на "\\\\", верьте или нет! Java действительно нуждается в хорошем синтаксисе строки.

12

Чтобы избежать такого рода проблем, вы можете использовать replace (который принимает простую строку) вместо replaceAll (что принимает регулярное выражение). Вам все равно придется скрывать обратную косую черту, но не в диких направлениях, требуемых регулярными выражениями.

4

replaceAll(target, replacement) использует регулярное выражение (regex) синтаксис для target и частично для replacement.

Проблема заключается в том, что \ является специальным символом в регулярном выражении (как \d к представляет цифру) и в строковом литерале (например, \n создать разделительную линию или \" представлять двойной символ кавычки), и создать \ символ нам нужно, чтобы избежать его с дополнительным \ перед этим на обоих этих уровнях.

Итак, чтобы создать target регулярное выражение, которое будет представлять \ символ, нам нужно, чтобы избежать его дважды:

  • в регулярных выражениях \\
  • Строки буквального "\\\\" (каждый \ нуждается в собственной дополнительной \ раньше).

В случае replacement\ также особенного, чтобы избежать еще один специальный символ, который $. Через $x запись, часть данных, соответствующая регулярному выражению, может быть доступна и использована повторно, например, replaceAll("(\d)", "$1$1") будет дублировать каждую цифру.

Итак, еще раз, чтобы иметь одного\ в replacement нам нужно текст, представляющий два обратных слеша:

  • \\
  • но строковый литерал, представляющие \\ выглядеть "\\\\"

НО так как мы хотим положить \ на замену нам нужен "\\\\\\\\" там (два "\\\\").

replaceAll("\\\\", "\\\\\\\\"); 

Оформлять жизнь проще Java предоставляет инструменты для автоматического избежать текста в target и replacement частей. Так что теперь мы можем сосредоточиться только на струнах, и забыть о регулярных выражений синтаксис:

replaceAll(Pattern.quote(target), Matcher.quoteReplacement(replacement)) 

в нашем случае может выглядеть

replaceAll(Pattern.quote("\\"), Matcher.quoteReplacement("\\\\")) 

Или еще проще, если мы не хотим использовать regex позволяет не включать replaceAll и вместо этого использовать replace (оба метода будут заменять все target s, но во втором случае не требуется синтаксис regex). Поэтому вы можете просто написать

theString = theString.replace("\\", "\\\\") 
Смежные вопросы