2010-10-01 4 views
1

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

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

+1

Можете ли вы просто использовать String.replace()? –

+0

Хорошо за пределами \ r \ n Я бы предпочел не заменять все возможные литералы \ X и \ uXXXX и т. Д. Вручную, если это возможно –

ответ

1

Администраторы Apache StringEscapeUtils.unescapeJava(...) будут выполнять эту работу. Хотя из описания javadoc неясно, эти методы обрабатывают escape-последовательности unicode, а также «обычные» escape-последовательности Java String.

+0

ОК, это именно то, что я ищу. Благодаря!! –

2

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

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

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

Примерно год назад я был соавтором компилятора Java для подмножества спецификации 1.3, у которой есть 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(); 
} 

Я надеюсь, что это поможет.

+0

Я правильно понял, что этот код не касается экранов Unicode? Это понятно для исходного прецедента для этого кода. Но комментарий OP о другом ответе предполагает, что ему нужно также переуступать unicode-экраны. –

+0

Ах да, вы совершенно правы - в разгар ответа я, должно быть, забыл, что одним из сокращений было то, что мы не поддерживали Юникод. Так что да, в этом нет никакой поддержки Unicode, поэтому приведенный выше код может в большинстве случаев сформировать скелет вокруг реализации, включая это. Отлично, что ты это понял. :-) – micdah

+0

Спасибо, что нашли время ответить и предоставить код. Btw, для unicode я мог бы добавить код, который имеет дело с unicode escapes. if (c == '\\') {if (i

Смежные вопросы