Избегание двойных слешей с регулярными выражениями в Java - PullRequest
4 голосов
/ 14 июня 2011

У меня есть этот юнит-тест:

public void testDeEscapeResponse() {
    final String[] inputs = new String[] {"peque\\\\u0f1o", "peque\\u0f1o"};
    final String[] expected = new String[] {"peque\\u0f1o", "peque\\u0f1o"};
    for (int i = 0; i < inputs.length; i++) {
        final String input = inputs[i];
        final String actual = QTIResultParser.deEscapeResponse(input);
        Assert.assertEquals(
            "deEscapeResponse did not work correctly", expected[i], actual);
    }
}

У меня есть этот метод:

static String deEscapeResponse(String str) {
    return str.replaceAll("\\\\", "\\");
}

Модульный тест не пройден с этой ошибкой:

java.lang.StringIndexOutOfBoundsException: String index out of range: 1
    at java.lang.String.charAt(String.java:686)
    at java.util.regex.Matcher.appendReplacement(Matcher.java:703)
    at java.util.regex.Matcher.replaceAll(Matcher.java:813)
    at java.lang.String.replaceAll(String.java:2189)
    at com.acme.MyClass.deEscapeResponse
    at com.acme.MyClassTest.testDeEscapeResponse

Почему?

Ответы [ 3 ]

4 голосов
/ 14 июня 2011

Используйте String.replace, который заменяет буквально вместо String.replaceAll, который использует регулярные выражения.

Пример:

"peque\\\\u0f1o".replace("\\\\", "\\")    //  gives  peque\u0f1o

String.replaceAll принимает регулярное выражение, поэтому \\\\ интерпретируется как выражение \\, которое в свою очередь соответствует одному \.(Строка замены также имеет специальную обработку для \, поэтому там тоже есть ошибка.)

Чтобы String.replaceAll работал так, как вы ожидаете, вам нужно будет сделать

"peque\\\\u0f1o".replaceAll("\\\\\\\\", "\\\\")
2 голосов
/ 14 июня 2011

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

1 голос
/ 14 июня 2011

См. Javadoc для Matcher:

Обратите внимание, что обратная косая черта (\) и знаки доллара ($) в строке замены могут привести к тому, что результаты будут отличаться отэто рассматривалось как буквальная строка замены.Знаки доллара могут рассматриваться как ссылки на захваченные подпоследовательности, как описано выше, а обратные слэши используются для экранирования литеральных символов в строке замены.

Таким образом, с replaceAll вы не можете заменить что-либо обратным слешем.Таким образом, действительно сумасшедший обходной путь для вашего случая будет str.replaceAll("\\\\(\\\\)", "$1")

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...