Интерпретация строки Java - PullRequest
1 голос
/ 02 октября 2010

Есть ли способ интерпретировать строку, такую ​​как "hello \ r \ n \ world", в строку, где \ r \ n был преобразован в их действительные литеральные значения.

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

Ответы [ 2 ]

2 голосов
/ 02 октября 2010

Я не знаком непосредственно с «простым» способом обработки этого (то есть, я не знаю, есть ли встроенная библиотека, которая может обработать это).Но один из способов сделать это - прочитать спецификацию JLS о escape-последовательностях и написать однопроходный синтаксический анализатор, который может найти и оценить каждую escape-последовательность.(Проверьте JLS 3.10.6 Escape-последовательности для символьных и строковых литералов ).

Теперь я точно знаю, что есть несколько странностей, с которыми вы быстро забудете разобраться, например:Пример восьмеричного экранирования сложен, потому что он допускает либо 1,2, либо 3 цифры, и в каждом случае есть разные допустимые значения, когда это экранирование, и когда это просто целое число.

Взять пример строки "\ 431 "это экранированный символ" \ 43 ", соединенный с символом" 1 ", потому что первая цифра восьмеричного экранирования равна 4, и, таким образом, не может быть целым трехзначным восьмеричным значением, поскольку допускается только [0-3]в качестве первой цифры в этом случае.

Примерно год назад я занимался совместным написанием Java-компилятора для подмножества спецификации 1.3, которая имеет escape-последовательности, и ниже здесь я включил наш код дляобработка Escape - вы должны иметь возможность воспринимать этот код буквально как есть и включать его в класс Utility (возможно, добавить кредит, если вы чувствуете себя благотворительным):

private String processCharEscapes(String strVal) {
    // Loop helpers
    char[]          chrArr = strVal.toCharArray();
    StringBuilder   strOut = new StringBuilder(strVal.length());
    String          strEsc = "";    // Escape sequence, string buffer
    Character       chrBuf = null;  // Dangling character buffer

    // Control flags
    boolean inEscape    = false;    // In escape?
    boolean cbOctal3    = true;     // Can be octal 3-digit

    // Parse characters
    for(char c : chrArr) {
        if (!inEscape) {
            // Listen for start of escape sequence
            if (c == '\\') {
                inEscape = true;    // Enter escape
                strEsc = "";        // Reset escape buffer
                chrBuf = null;      // Reset dangling character buffer
                cbOctal3 = true;    // Reset cbOctal3 flag
            } else {
                strOut.append(c);   // Save to output
            }
        } else {
            // Determine escape termination
            if (strEsc.length() == 0) { // First character
                if (c >= 48 && c <= 55) {   // c is a digit [0-7]
                    if (c > 51) {   // c is a digit [4-7]
                        cbOctal3 = false;
                    }
                    strEsc += c;    // Save to buffer
                } else {    // c is a character
                    // Single-character escapes (will terminate escape loop)
                    if (c == 'n') {
                        inEscape = false;
                        strOut.append('\n');
                    } else if(c == 't') {
                        inEscape = false;
                        strOut.append('\t');
                    } else if(c == 'b') {
                        inEscape = false;
                        strOut.append('\b');
                    } else if(c == 'r') {
                        inEscape = false;
                        strOut.append('\r');
                    } else if(c == 'f') {
                        inEscape = false;
                        strOut.append('\f');
                    } else if(c == '\\') {
                        inEscape = false;
                        strOut.append('\\');
                    } else if(c == '\'') {
                        inEscape = false;
                        strOut.append('\'');
                    } else if(c == '"') {
                        inEscape = false;
                        strOut.append('"');
                    } else {
                        // Saw illegal character, after escape character '\'
                        System.err.println(ErrorType.SYNTAX_ERROR, "Illegal character escape sequence, unrecognised escape: \\" + c);
                    }
                }
            } else if(strEsc.length() == 1) {   // Second character (possibly)
                if (c >= 48 && c <= 55) {   // c is a digit [0-7]
                    strEsc += c;    // Save to buffer
                    if (!cbOctal3) {    // Terminate since !cbOctal3
                        inEscape = false;
                    }
                } else {
                    inEscape = false;   // Terminate since c is not a digit
                    chrBuf = c;         // Save dangling character
                }
            } else if(strEsc.length() == 2) {   // Third character (possibly)
                if (cbOctal3 && c >= 48 && c <= 55) {
                    strEsc += c;        // Save to buffer
                } else {
                    chrBuf = c;         // Save dangling character
                }
                inEscape = false;       // Will always terminate after third character, no matter what
            }

            // Did escape sequence terminate, at character c?
            if (!inEscape && strEsc.length() > 0) {
                // strEsc is legal 1-3 digit octal char code, convert and add
                strOut.append((char)Integer.parseInt(strEsc, 8));

                if (chrBuf != null) {   // There was a dangling character
                    // Check for chained escape sequences (e.g. \10\10)
                    if (chrBuf == '\\') {
                        inEscape = true;    // Enter escape
                        strEsc = "";        // Reset escape buffer
                        chrBuf = null;      // Reset dangling character buffer
                        cbOctal3 = true;    // Reset cbOctal3 flag
                    } else {
                        strOut.append(chrBuf);
                    }
                }
            }
        }
    }

    // Check for EOL-terminated escape sequence (special case)
    if (inEscape) {
        // strEsc is legal 1-3 digit octal char code, convert and add
        strOut.append((char)Integer.parseInt(strEsc, 8));

        if (chrBuf != null) {   // There was a dangling character
            strOut.append(chrBuf);
        }
    }

    return strOut.toString();
}

Надеюсь, это поможет вам.

1 голос
/ 02 октября 2010

Apache commons StringEscapeUtils.unescapeJava(...) методы сделают эту работу.Хотя это не ясно из описания javadoc, эти методы обрабатывают экранированные символы Юникода, а также "обычные" экранированные строки Java.

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